跳转至

base

汇编语言(第4版) -- 王爽

AT&T格式汇编语言

csapp学习,知识点快速预览,细节参考原书

一、数据格式对照

p119

C声明 Inter数据类型 汇编代码后缀 大小(字节)
char byte b 1
short word w 2
int long-word l 4
long quad-word q 8
char* quad-word q 8
float 单精度 s 4
double 双精度 l 8

汇编代码后缀决定了操作数的大小,例如mov指令:

  • movb: 传送字节
  • movw: 传送字
  • movl: 传送双字
  • movq: 传送四字

二、寄存器

寄存器中,字母寄存器是历史原因,在16位也就是时代的表示方法,扩展而来。 而在后续添加的数字寄存器则采用了不同的命名方式,其中,r表示四字,e表示双字,w表示字,b表示字节。 %开头为AT&T规范的标准,没有特殊含义。

63<-- 31<-- 15<-- 7<--0
%rax %eax %ax %al
%rbx %ebx %bx %bl
%rcx %ecx %cx %cl
%rdx %edx %dx %dl
%rsi %esi %si %sil
%rdi %edi %di %dil
%rbp %ebp %bp %bpl
%rsp %esp %sp %spl
%r8 %r8d %r8w %r8b
%r9 %r9d %r9w %r9b
%r10 %r10d %r10w %r10b
%r11 %r11d %r11w %r11b
%r12 %r12d %r12w %r12b
%r13 %r13d %r13w %r13b
%r14 %r14d %r14w %r14b
%r15 %r15d %r15w %r15b

三、操作数

有三类操作数: * 立即数,即常数值,书写方式是$后面跟一个标准c表示法表示的整数,例如$-577$0x1F。 * 寄存器 p120 * 内存引用 p121

四、数据传送指令

movq %rbx,%rax 等于 %rax = %rbx

  • movb: 传送字节
  • movw: 传送字
  • movl: 传送双字
  • movq: 传送四字
  • movabsq: 传送绝对四字,movq只能以32位补码数字的立即数,根据符号位扩展至64位。而movabsq则可以直接用64位立即数作为操作源。

在将较小的源值复制到较大的目的值时,我们将会使用零扩展数据传送指令或者符号扩展数据传送指令:

零扩展数据传送指令(movz),将复制并将高位置零: * movzbw bw表示从b扩展到w,下列表示同义 * movzbl * movzbq * movzwl * movzwq

符号扩展数据传送指令(movs),复制并根据最高位设置高位: * movsbw * movsbl * movsbq * movswl * movswq * movslq * cltq 特指将%eax符号扩展至%rax

五、算术和逻辑操作

加载有效地址: * leaq 功能和mov类似,但是只能针对寄存器操作,用于计算内存地址。

一元操作: * inc n++ * dec n-- * neg 取负 * not 取反

二元操作: * add x=x+y * sub x=x-y * imul x=x*y * or x=x|y * xor x=x^y 异或 有一个是一则为一,都为一则为零,都是零还是零 * and x=x&y

移位: * sal 左移 * shl 左移 等同于sal * sar 算术右移 填符号位 * shr 逻辑右移 填零

乘除: * imul 乘法,两个64位操作数产生一个64位的乘积,超过64位截取到64位,此指令包含在imulq中,由汇编器根据操作数决定使用哪条指令 * imulq 有符号全乘法,一个64位操作数与%rax产生一个128位的乘积,高8字节在%rdx,低8字节在%rax * mulq 无符号全乘法,一个64位操作数与%rax产生一个128位的乘积,高8字节在%rdx,低8字节在%rax * idivq 有符号除法,由%rdx:%rax组成的128位数除以一个64操作数,余数存储在%rdx,商存储在%rax * divq 无符号除法,由%rdx:%rax组成的128位数除以一个64操作数,余数存储在%rdx,商存储在%rax * cqto 将%rax符号扩展成128位,使用%rax的符号位填充%rdx,通常在被除数是64位时使用

六、条件码寄存器

除了整数寄存器,cpu还维护着一组单个位的条件码寄存器,它们描述了最近的算术逻辑操作的属性。

常用条件码: * CF 进位标志 最近的操作使最高位产生了进位 可以用来检测无符号操作的溢出 * ZF 零标志 最近的操作得出的结果为0 * SF 符号标志 最近的操作得到的结果为负数 * OF 溢出标志 最近的操作导致一个补码溢出--正溢出或负溢出

设置条件码: * cmp 指令行为与sub相同 但不输出结果 只设置条件码寄存器 * test 指令行为与and相同 但不输出结果 只设置条件码寄存器

访问条件码,条件码通常不会直接读取,常用方法有三种: 1. 根据条件码的某种组合,将一个字节设置位0或者1。 2. 条件跳转到程序的某个其他部分。 3. 有条件的传送数据。