Tan's Blog.

CSAPP汇编指令1

字数统计: 1.1k阅读时长: 3 min
2019/05/10 Share

计算机系统学习

开始学习第三章程序的机器级表示,我竟然惊喜地发现这一章的内容正是我想学习但一直没找到汇总很好的学习资源。这两天主要在学习关于汇编指令的基础知识。

为什么要学习汇编

有的人说,汇编语言的可读性和可移植性都很差,高级语言很容易理解、兼容性很好。为什么要学汇编语言而不是高级语言?
因为想要真正了解计算机系统,了解计算机是如何工作的,想要做一些漏洞分析,汇编语言都是必不可少的。

生成汇编代码

一般生成汇编代码有两种途径,一种是从高级语言生成汇编代码,这时可以借助gcc编译器,比如在Linux环境下,使用命令

> gcc -Og -S xx.c

就可以看到C语言编译器产生的汇编代码了;而另一种是对可执行程序反汇编生成汇编代码,在Linux上一般使用objdump工具,敲命令行

> objdump -d xx.o

汇编指令概述

汇编代码格式
汇编代码格式有两种,分别是是ATT和Intel格式,关于这两种汇编格式,在我之前的博客中做过总结。本书中用到的都是ATT格式的汇编代码。
数据格式

寄存器
寄存器是CPU当中非常重要的对象,一般情况下,很多临时变量都会存储在这里.下面是一张书中的寄存器图示,它基于IA32架构给出。

操作数指令符
不同指令符的表示方式一共有三种,一种是$符号后跟一个标准C表示的整数,比如$100,$0x11等等。第二种则是寄存器,当它作为一个操作数的时候,则是取的寄存器当中的数值。另外,对于寄存器来说,也可以选择性的操作4个、2个、1个字节,而并不一定非要操作4个字节。最后一种,则是我们相对来说最熟悉的,就是存储器或者说内存。当它作为一个操作数的时候,会去计算存储器地址的数值,然后去这个地址取相应的数值。

数据传送指令

数据传送指令的目的是为了将一个数据从一个位置复制到另外一个位置。既然如此,那么数据传送指令就会包含一个源操作数和一个目的操作数,指令会将原操作数的值复制到目的操作数并覆盖。
数据传送指令一共可分为五种,分别是mov、movs、movz、push以及pop。这几种指令之前也分别做过总结,通过学习本节更系统地了解这些指令,算是复习了一遍吧。

算术与逻辑运算操作指令

算术与逻辑运算包括很多种,比如最常见的加减乘除、与或非、左移右移等等。基本的加减乘除,位操作都比较基础了,这里就不再多说。通过本书我还学到了一个很精妙的指令,就是取地址运算符leaq。
leaq指令是非常神奇的一个指令,它可以取一个存储器操作数的地址,并且将其赋给目的操作数。如果用C语言当中来对应的话,它就相当于&运算。
比如对于leaq 4(%rdx,%rdx,4),%rax这条指令来讲,我们假设%rdx寄存器的值为x的话,那么这条指令的作用就是将 4 + x + 4x = 5x + 4赋给%rax寄存器。它和mov指令的区别就在于,假设是movq 4(%rdx,%rdx,4),%rax这个指令,它的作用是将内存地址为5x+4的内存区域的值赋给%rax寄存器,而leaq指令只是将5x+4这个地址赋给目的操作数%rax而已,它并不对存储器进行引用的值的计算。
leaq指令能执行加法和有限形式的乘法,在编译一些比较复杂的算术表达式,使用leaq指令就会变得很简单,能有效减少程序的大小,提高代码执行效率。

CATALOG
  1. 1. 计算机系统学习
    1. 1.1. 为什么要学习汇编
    2. 1.2. 生成汇编代码
    3. 1.3. 汇编指令概述
    4. 1.4. 数据传送指令
    5. 1.5. 算术与逻辑运算操作指令