GAS中每个操作都是有一个字符的后缀,表明操作数的大小。 C声明 | GAS后缀 | 大小(字节) | char | b | 1 | short | w | 2 | (unsigned) int / long / char* | l | 4 | float | s | 4 | double | l | 8 | long double | t | 10/12 |
注意:GAL使用后缀“l”同时表示4字节整数和8字节双精度浮点数,这不会产生歧义因为浮点数使用的是完全不同的指令和寄存器。
操作数格式: 格式 | 操作数值 | 名称 | 样例(GAS = C语言) | $Imm | Imm | 立即数寻址 | $1 = 1 | Ea | R[Ea] | 寄存器寻址 | %eax = eax | Imm | M[Imm] | 绝对寻址 | 0x104 = *0x104 | (Ea) | M[R[Ea]] | 间接寻址 | (%eax)= *eax | Imm(Ea) | M[Imm+R[Ea]] | (基址+偏移量)寻址 | 4(%eax) = *(4+eax) | (Ea,Eb) | M[R[Ea]+R[Eb]] | 变址 | (%eax,%ebx) = *(eax+ebx) | Imm(Ea,Eb) | M[Imm+R[Ea]+R[Eb]] | 寻址 | 9(%eax,%ebx)= *(9+eax+ebx) | (,Ea,s) | M[R[Ea]*s] | 伸缩化变址寻址 | (,%eax,4)= *(eax*4) | Imm(,Ea,s) | M[Imm+R[Ea]*s] | 伸缩化变址寻址 | 0xfc(,%eax,4)= *(0xfc+eax*4) | (Ea,Eb,s) | M(R[Ea]+R[Eb]*s) | 伸缩化变址寻址 | (%eax,%ebx,4) = *(eax+ebx*4) | Imm(Ea,Eb,s) | M(Imm+R[Ea]+R[Eb]*s) | 伸缩化变址寻址 | 8(%eax,%ebx,4) = *(8+eax+ebx*4) |
注:M[xx]表示在存储器中xx地址的值,R[xx]表示寄存器xx的值,这种表示方法将寄存器、内存都看出一个大数组的形式。
数据传送指令: 指令 | 效果 | 描述 | movl S,D | D <-- S | 传双字 | movw S,D | D <-- S | 传字 | movb S,D | D <-- S | 传字节 | movsbl S,D | D <-- 符号扩展S | 符号位填充(字节->双字) | movzbl S,D | D <-- 零扩展S | 零填充(字节->双字) | pushl S | R[%esp] <-- R[%esp] – 4; M[R[%esp]] <-- S | 压栈 | popl D | D <-- M[R[%esp]]; R[%esp] <-- R[%esp] + 4; | 出栈 |
注:均假设栈往低地址扩展。
算数和逻辑操作地址: 指令 | 效果 | 描述 | leal S,D | D = &S | movl地版,S地址入D,D仅能是寄存器 | incl D | D++ | 加1 | decl D | D-- | 减1 | negl D | D = -D | 取负 | notl D | D = ~D | 取反 | addl S,D | D = D + S | 加 | subl S,D | D = D – S | 减 | imull S,D | D = D*S | 乘 | xorl S,D | D = D ^ S | 异或 | orl S,D | D = D | S | 或 | andl S,D | D = D & S | 与 | sall k,D | D = D << k | 左移 | shll k,D | D = D << k | 左移(同sall) | sarl k,D | D = D >> k | 算数右移 | shrl k,D | D = D >> k | 逻辑右移 |
特殊算术操作: 指令 | 效果 | 描述 | imull S | R[%edx]:R[%eax] = S * R[%eax] | 无符号64位乘 | mull S | R[%edx]:R[%eax] = S * R[%eax] | 有符号64位乘 | cltd S | R[%edx]:R[%eax] = 符号位扩展R[%eax] | 转换为4字节 | idivl S | R[%edx] = R[%edx]:R[%eax] % S; R[%eax] = R[%edx]:R[%eax] / S; | 有符号除法,保存余数和商 | divl S | R[%edx] = R[%edx]:R[%eax] % S; R[%eax] = R[%edx]:R[%eax] / S; | 无符号除法,保存余数和商 |
注:64位数通常存储为,高32位放在edx,低32位放在eax。
条件码: 条件码寄存器描述了最近的算数或逻辑操作的属性。 CF:进位标志,最高位产生了进位,可用于检查无符号数溢出。 OF:溢出标志,二进制补码溢出——正溢出或负溢出。 ZF:零标志,结果为0。 SF:符号标志,操作结果为负。
比较指令: 指令 | 基于 | 描述 | cmpb S2,S1 | S1 – S2 | 比较字节,差关系 | testb S2,S1 | S1 & S2 | 测试字节,与关系 | cmpw S2,S1 | S1 – S2 | 比较字,差关系 | testw S2,S1 | S1 & S2 | 测试字,与关系 | cmpl S2,S1 | S1 – S2 | 比较双字,差关系 | testl S2,S1 | S1 & S2 | 测试双字,与关系 |
访问条件码指令: 指令 | 同义名 | 效果 | 设置条件 | sete D | setz | D = ZF | 相等/零 | setne D | setnz | D = ~ZF | 不等/非零 | sets D |
| D = SF | 负数 | setns D |
| D = ~SF | 非负数 | setg D | setnle | D = ~(SF ^OF) & ZF | 大于(有符号>) | setge D | setnl | D = ~(SF ^OF) | 小于等于(有符号>=) | setl D | setnge | D = SF ^ OF | 小于(有符号<) | setle D | setng | D = (SF ^ OF) | ZF | 小于等于(有符号<=) | seta D | setnbe | D = ~CF & ~ZF | 超过(无符号>) | setae D | setnb | D = ~CF | 超过或等于(无符号>=) | setb D | setnae | D = CF | 低于(无符号<) | setbe D | setna | D = CF | ZF | 低于或等于(无符号<=) |
跳转指令: 指令 | 同义名 | 跳转条件 | 描述 | jmp Label |
| 1 | 直接跳转 | jmp *Operand |
| 1 | 间接跳转 | je Label | jz | ZF | 等于/零 | jne Label | jnz | ~ZF | 不等/非零 | js Label |
| SF | 负数 | jnz Label |
| ~SF | 非负数 | jg Label | jnle | ~(SF^OF) & ~ZF | 大于(有符号>) | jge Label | jnl | ~(SF ^ OF) | 大于等于(有符号>=) | jl Label | jnge | SF ^ OF | 小于(有符号<) | jle Label | jng | (SF ^ OF) | ZF | 小于等于(有符号<=) | ja Label | jnbe | ~CF & ~ZF | 超过(无符号>) | jae Label | jnb | ~CF | 超过或等于(无符号>=) | jb Label | jnae | CF | 低于(无符号<) | jbe Label | jna | CF | ZF | 低于或等于(无符号<=) |
转移控制指令:(函数调用): 指令 | 描述 | call Label | 过程调用,返回地址入栈,跳转到调用过程起始处,返回地址是call后面那条指令的地址 | call *Operand | leave | 为返回准备好栈,为ret准备好栈,主要是弹出函数内的栈使用及%ebp |
|