GAS中每个操作都是有一个字符的后缀,表明操作数的大小。

C声明</p>
</td>

GAS后缀</p>
</td>

大小(字节)</p>
</td>
</tr>

char</p>
</td>

b</p>
</td>

1</p>
</td>
</tr>

short</p>
</td>

w</p>
</td>

2</p>
</td>
</tr>

(unsigned) int / long / char*</p>
</td>

l</p>
</td>

4</p>
</td>
</tr>

float</p>
</td>

s</p>
</td>

4</p>
</td>
</tr>

double</p>
</td>

l</p>
</td>

8</p>
</td>
</tr>

long double</p>
</td>

t</p>
</td>

10/12</p>
</td>
</tr>
</tbody>
</table>
注意:GAS使用后缀“l”同时表示4字节整数和8字节双精度浮点数,这不会产生歧义因为浮点数使用的是完全不同的指令和寄存器。

操作数格式:</strong></p>

格式</p>
</td>

操作数值</p>
</td>

名称</p>
</td>

样例(GAS = C语言)</p>
</td>
</tr>

$Imm</p>
</td>

Imm</p>
</td>

立即数寻址</p>
</td>

$1 = 1</p>
</td>
</tr>

Ea</p>
</td>

R[Ea]</p>
</td>

寄存器寻址</p>
</td>

%eax = eax</p>
</td>
</tr>

Imm</p>
</td>

M[Imm]</p>
</td>

绝对寻址</p>
</td>

0x104 = *0x104</p>
</td>
</tr>

(Ea)</p>
</td>

M[R[Ea]]</p>
</td>

间接寻址</p>
</td>

(%eax)= *eax</p>
</td>
</tr>

Imm(Ea)</p>
</td>

M[Imm+R[Ea]]</p>
</td>

(基址+偏移量)寻址</p>
</td>

4(%eax) = *(4+eax)</p>
</td>
</tr>

(Ea,Eb)</p>
</td>

M[R[Ea]+R[Eb]]</p>
</td>

变址</p>
</td>

(%eax,%ebx) = *(eax+ebx)</p>
</td>
</tr>

Imm(Ea,Eb)</p>
</td>

M[Imm+R[Ea]+R[Eb]]</p>
</td>

寻址</p>
</td>

9(%eax,%ebx)= *(9+eax+ebx)</p>
</td>
</tr>

(,Ea,s)</p>
</td>

M[R[Ea]*s]</p>
</td>

伸缩化变址寻址</p>
</td>

(,%eax,4)= *(eax*4)</p>
</td>
</tr>

Imm(,Ea,s)</p>
</td>

M[Imm+R[Ea]*s]</p>
</td>

伸缩化变址寻址</p>
</td>

0xfc(,%eax,4)= *(0xfc+eax*4)</p>
</td>
</tr>

(Ea,Eb,s)</p>
</td>

M(R[Ea]+R[Eb]*s)</p>
</td>

伸缩化变址寻址</p>
</td>

(%eax,%ebx,4) = *(eax+ebx*4)</p>
</td>
</tr>

Imm(Ea,Eb,s)</p>
</td>

M(Imm+R[Ea]+R[Eb]*s)</p>
</td>

伸缩化变址寻址</p>
</td>

8(%eax,%ebx,4) = *(8+eax+ebx*4)</p>
</td>
</tr>
</tbody>
</table>
注:M[xx]表示在存储器中xx地址的值,R[xx]表示寄存器xx的值,这种表示方法将寄存器、内存都看出一个大数组的形式。

数据传送指令:</strong></p>

指令</td></p> 效果</td></p> 描述</td>
</tr></p>
movl S,D</td></p> D <-- S</td></p> 传双字</td>
</tr></p>
movw S,D</td></p> D <-- S</td></p> 传字</td>
</tr></p>
movb S,D</td></p> D <-- S</td></p> 传字节</td>
</tr></p>
movsbl S,D</td></p> D <-- 符号扩展S</td></p> 符号位填充(字节->双字)</td>
</tr></p>
movzbl S,D</td></p> D <-- 零扩展S</td></p> 零填充(字节->双字)</td>
</tr></p>
pushl S</td></p> R[%esp] <-- R[%esp] – 4;M[R[%esp]] <-- S</td></p> 压栈</td>
</tr></p>
popl D</td></p> D <-- M[R[%esp]];R[%esp] <-- R[%esp] + 4;</td></p> 出栈</td>
</tr>
</tbody>
</table>
注:均假设栈往低地址扩展。</p>

算数和逻辑操作地址:</strong></p>

指令</td></p> 效果</td></p> 描述</td>
</tr></p>
leal S,D</td></p> D = &S</td></p> movl地版,S地址入D,D仅能是寄存器</td>
</tr></p>
incl D</td></p> D++</td></p> 加1</td>
</tr></p>
decl D</td></p> D--</td></p> 减1</td>
</tr></p>
negl D</td></p> D = -D</td></p> 取负</td>
</tr></p>
notl D</td></p> D = ~D</td></p> 取反</td>
</tr></p>
addl S,D</td></p> D = D + S</td></p> 加</td>
</tr></p>
subl S,D</td></p> D = D – S</td></p> 减</td>
</tr></p>
imull S,D</td></p> D = D*S</td></p> 乘</td>
</tr></p>
xorl S,D</td></p> D = D ^ S</td></p> 异或</td>
</tr></p>
orl S,D</td></p> D = D | S</td></p> 或</td>
</tr></p>
andl S,D</td></p> D = D & S</td></p> 与</td>
</tr></p>
sall k,D</td></p> D = D << k</td></p> 左移</td>
</tr></p>
shll k,D</td></p> D = D << k</td></p> 左移(同sall)</td>
</tr></p>
sarl k,D</td></p> D = D >> k</td></p> 算数右移</td>
</tr></p>
shrl k,D</td></p> D = D >> k</td></p> 逻辑右移</td>
</tr>
</tbody>
</table>
特殊算术操作:</strong></p>
指令</td></p> 效果</td></p> 描述</td>
</tr></p>
imull S</td></p> R[%edx]:R[%eax] = S * R[%eax]</td></p> 无符号64位乘</td>
</tr></p>
mull S</td></p> R[%edx]:R[%eax] = S * R[%eax]</td></p> 有符号64位乘</td>
</tr></p>
cltd S</td></p> R[%edx]:R[%eax] = 符号位扩展R[%eax]</td></p> 转换为4字节</td>
</tr></p>
idivl S</td></p> R[%edx] = R[%edx]:R[%eax] % S;R[%eax] = R[%edx]:R[%eax] / S;</td></p> 有符号除法,保存余数和商</td>
</tr></p>
divl S</td></p> R[%edx] = R[%edx]:R[%eax] % S;R[%eax] = R[%edx]:R[%eax] / S;</td></p> 无符号除法,保存余数和商</td>
</tr>
</tbody>
</table>
注:64位数通常存储为,高32位放在edx,低32位放在eax。</p>

条件码:</strong></p>

条件码寄存器描述了最近的算数或逻辑操作的属性。

CF:进位标志,最高位产生了进位,可用于检查无符号数溢出。

OF:溢出标志,二进制补码溢出——正溢出或负溢出。

ZF:零标志,结果为0。

SF:符号标志,操作结果为负。

比较指令:</strong></p>

指令</td></p> 基于</td></p> 描述</td>
</tr></p>
cmpb S2,S1</td></p> S1 – S2</td></p> 比较字节,差关系</td>
</tr></p>
testb S2,S1</td></p> S1 & S2</td></p> 测试字节,与关系</td>
</tr></p>
cmpw S2,S1</td></p> S1 – S2</td></p> 比较字,差关系</td>
</tr></p>
testw S2,S1</td></p> S1 & S2</td></p> 测试字,与关系</td>
</tr></p>
cmpl S2,S1</td></p> S1 – S2</td></p> 比较双字,差关系</td>
</tr></p>
testl S2,S1</td></p> S1 & S2</td></p> 测试双字,与关系</td>
</tr>
</tbody>
</table>
访问条件码指令:</strong></p>
指令</td></p> 同义名</td></p> 效果</td></p> 设置条件</td>
</tr></p>
sete D</td></p> setz</td></p> D = ZF</td></p> 相等/零</td>
</tr></p>
setne D</td></p> setnz</td></p> D = ~ZF</td></p> 不等/非零</td>
</tr></p>
sets D</td></p> </td></p> D = SF</td></p> 负数</td>
</tr></p>
setns D</td></p> </td></p> D = ~SF</td></p> 非负数</td>
</tr></p>
setg D</td></p> setnle</td></p> D = ~(SF ^OF) & ZF</td></p> 大于(有符号>)</td>
</tr></p>
setge D</td></p> setnl</td></p> D = ~(SF ^OF)</td></p> 小于等于(有符号>=)</td>
</tr></p>
setl D</td></p> setnge</td></p> D = SF ^ OF</td></p> 小于(有符号<)</td>
</tr></p>
setle D</td></p> setng</td></p> D = (SF ^ OF) | ZF</td></p> 小于等于(有符号<=)</td>
</tr></p>
seta D</td></p> setnbe</td></p> D = ~CF & ~ZF</td></p> 超过(无符号>)</td>
</tr></p>
setae D</td></p> setnb</td></p> D = ~CF</td></p> 超过或等于(无符号>=)</td>
</tr></p>
setb D</td></p> setnae</td></p> D = CF</td></p> 低于(无符号<)</td>
</tr></p>
setbe D</td></p> setna</td></p> D = CF | ZF</td></p> 低于或等于(无符号<=)</td>
</tr>
</tbody>
</table>
跳转指令:</strong></p>
指令</td></p> 同义名</td></p> 跳转条件</td></p> 描述</td>
</tr></p>
jmp   Label</td></p> </td></p> 1</td></p> 直接跳转</td>
</tr></p>
jmp   *Operand</td></p> </td></p> 1</td></p> 间接跳转</td>
</tr></p>
je     Label</td></p> jz</td></p> ZF</td></p> 等于/零</td>
</tr></p>
jne    Label</td></p> jnz</td></p> ~ZF</td></p> 不等/非零</td>
</tr></p>
js     Label</td></p> </td></p> SF</td></p> 负数</td>
</tr></p>
jnz    Label</td></p> </td></p> ~SF</td></p> 非负数</td>
</tr></p>
jg     Label</td></p> jnle</td></p> ~(SF^OF) & ~ZF</td></p> 大于(有符号>)</td>
</tr></p>
jge    Label</td></p> jnl</td></p> ~(SF ^ OF)</td></p> 大于等于(有符号>=)</td>
</tr></p>
jl     Label</td></p> jnge</td></p> SF ^ OF</td></p> 小于(有符号<)</td>
</tr></p>
jle     Label</td></p> jng</td></p> (SF ^ OF) | ZF</td></p> 小于等于(有符号<=)</td>
</tr></p>
ja     Label</td></p> jnbe</td></p> ~CF & ~ZF</td></p> 超过(无符号>)</td>
</tr></p>
jae    Label</td></p> jnb</td></p> ~CF</td></p> 超过或等于(无符号>=)</td>
</tr></p>
jb     Label</td></p> jnae</td></p> CF</td></p> 低于(无符号<)</td>
</tr></p>
jbe    Label</td></p> jna</td></p> CF | ZF</td></p> 低于或等于(无符号<=)</td>
</tr>
</tbody>
</table>
转移控制指令:(函数调用):</strong></p>
指令</td></p> 描述</td>
</tr></p>
call    Label</td></p> 过程调用,返回地址入栈,跳转到调用过程起始处,返回地址是call后面那条指令的地址</td>
</tr></p>
call    *Operand</td>
</tr></p>
leave</td></p> 为返回准备好栈,为ret准备好栈,主要是弹出函数内的栈使用及%ebp</td>
</tr>
</tbody>
</table>
 </p>