汇编指令和标志寄存器
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 |
源文档 <http://www.cnblogs.com/lxgeek/archive/2011/01/01/1923738.html>
标志寄存器(Flags Register,FR)又称程序状态字(Program Status Word,PSW)。这是一个存放条件标志、控制标志寄存器,主要用于反映处理器的状态和运算结果的某些特征及控制指令的执行。
各标志在标志寄存器中的位置:
各标志位名称、英文全称、标志值符号及含义一览:
标志位 |
标志位名称/英文 |
状态符号表示 |
|
|
|
=1 |
=0 |
CF |
进位标志/Carry Flag |
CY/Carry/进位 |
NC/No Carry/无进位 |
PF |
奇偶标志/Parity Flag |
PE/Parity Even/偶 |
PO/Parity Odd/奇 |
AF |
辅助进位标志/Auxiliary Carry Flag |
AC/Auxiliary Carry/进位 |
NA/No Auxiliary Carry/无进位 |
ZF |
零标志/Zero Flag |
ZR/Zero/等于零 |
NZ/Not Zero/不等于零 |
SF |
符号标志/Sign Flag |
NG/Negative/负 |
PL/Plus/正 |
TF |
陷阱标志/Trap Flag |
|
|
IF |
中断标志/Interrupt Flag |
EI/Enable Interrupt/允许 |
DI/Disable Interrupt/禁止 |
DF |
方向标志/Direction Flag |
DN/Down/减少 |
UP/增加 |
OF |
溢出标志/Overflow Flag |
OV/Overflow/溢出 |
NV/Not Overflow/未溢出 |
条件标志:
CF(Carry Flag)进位标志:用于反映运算是否产生进位或借位。如果运算结果的最高位产生一个进位或借位,则CF置1,否则置0。运算结果的最高位包括字操作的第15位和字节操作的第7位。移位指令也会将操作数的最高位或最低位移入CF。
PF(Parity Flag)奇偶标志:用于反映运算结果中“1”的个数。“1”的个数为偶数,则PF置1,否则置0。
AF(Auxiliary Carry Flag)辅助进位标志:在字节操作时低半字节向高半字节进位或借位,字操作时低字节向高字节进位或借位,AF置1,否则置0。
ZF(Zero Flag)零标志:用于判断结果是否为0。运算结果0,ZF置1,否则置0。
SF(Sign Flag)符号标志:用于反映运算结果的符号,运算结果为负,SF置1,否则置0。因为有符号数采用补码的形式表示,所以SF与运算结果的最高位相同。
OF(Overflow Flag)溢出标志:反映有符号数加减运算是否溢出。如果运算结果超过了8位或者16位有符号数的表示范围,则OF置1,否则置0。
控制标志:
TF(Trap Flag)陷阱标志:当TF被设置位1时,CPU进入单步模式,所谓单步模式就是CPU在每执行一步指令后都产生一个单步中断。主要用于程序的调试。8086/8088中没有专门用来置位和清零TF的命令,需要用其他办法。
IF(Interrupt Flag)中断标志:决定CPU是否响应外部可屏蔽中断请求。TF为1时,CPU允许响应外部的可屏蔽中断请求。
DF(Direction Flag)方向标志:决定串操作指令执行时有关指针寄存器调整方向。当DF为1时,串操作指令按递减方式改变有关存储器指针值,每次操作后使SI、DI递减。