实践过程中的一些汇编指令及含义的积累。
指令 | 含义 | 补充 | 指令系统 | |
---|---|---|---|---|
cbw 、cwd 、cdq 、cwde 、cdqe |
符号拓展指令 | 见图1 | ||
sidt |
存储全局/中断描述符表格寄存器 | 将全局描述符表格寄存器 (GDTR) 或中断描述符表格寄存器 (IDTR) 中的内容存储到目标操作数。示例见图2. | x86 | |
JCC |
汇编跳转指令 | 详细描述见下 | x86 | |
STOS 、STOSB 、STOSW 、STOSD |
字符串存储指令 | 详细说明见图3(1),示例见图3(2)所示。 | x86 | |
REPNE/REPNZ |
重复前缀,当ECX!=0并且ZF==0时 重复执行后边的指令 每执行一次ECX的值减1 | REPNE和REPNZ是同一条指令的不同助记符,可配合其他指令,用于计算字符串长度、定位特定字符等。示例如图4 | x86 | |
STOS |
将eax中的值拷贝到ES:EDI指向的地址 | … | x86 | |
neg |
求补指令,对操作数执行求补运算:用零减去操作数,然后结果返回操作数。也可以表达成:将操作数按位取反后加1。 | 对标志的影响与用零作减法的SUB指令一样,可用于求一个数的相反数 | x86 | |
not |
把操作数按位取反 | NEG比NOT指令多了一步“加一”操作 | x86 | |
LEA |
目标地址传送指令 | 将一个地址指针写入到指定的寄存器,区别MOV传送指令:MOV传送的是地址所指的内容,而LEA只是地址 | x86 | |
SCASB |
详细描述见图5 | … | x86 | |
CMP |
详细描述见图6 | … | x86 | |
Test |
对两个参数(目标,源)执行AND逻辑操作,并根据结果设置标志寄存器(影响标志: C,O,P,Z,S(其中C与O两个标志会被设为0)),结果本身不会保存。TEST AX,BX 与 AND AX,BX 命令有相同效果 |
Test可以用来测试一个位,例如寄存器:test eax, 100b ; b后缀意为二进制 jnz ** ; 如果eax右数第三个位为1,jnz将会跳转; 另一个非常普遍的用法是用来测试寄存器是否为空,如test ecx, ecx |
x86 | |
cdq |
把 EAX 的第 31 bit 复制到 EDX 的每一个 bit 上,它实际的作用只是把EDX的所有位都设成EAX最高位的值。也就是说,当EAX <80000000, EDX 为00000000;当EAX >= 80000000, EDX 则为FFFFFFFF。 | 大多出现在除法运算之前 | x86 | |
div/idiv |
无符号/带符号除法指令 | 如图7 | x86 | |
sar 、shr |
汇编语言中SAR和SHR指令都是右移指令,SAR是算数右移指令(shift arithmetic right),而SHR是逻辑右移指令(shift logical right) | 两者的区别在于SAR右移时保留操作数的符号,即用符号位来补足,而SHR右移时总是用0来补足;例如10000000算数右移一位是11000000,而逻辑右移一位是01000000 | x86 | |
Movsx 、Movsxd |
符号扩展指令 | 符号扩展/传送指令有两大类:movsx系列和cbw系列,详细说明见图8 | x86 | |
Movzx |
零扩展指令 | 详细说明见图9 | x86 | |
CMOVcc |
有条件的移动指令 | 该指令检查EFLAGS寄存器(CF,OF,PF,SF和ZF)中的一个或多个状态标志的状态,并在标志处于指定状态(或条件)时执行移动操作。条件代码(cc)与每个指令相关联以指示正在测试的条件。如果不满足条件,则不执行移动并继续执行CMOV cc指令之后的指令。详细描述如图10(1)(2)所示。 | x86 | |
setne |
检查ZF标志位,并按照其值将后面的寄存器赋值为相反的值。 | 如cmp eax,06 setne al ,若eax等于6,ZF等于1,则赋值al=0,反之则赋值al=1。 |
x86 | |
sbb |
借位减法指令 | 如sbb eax,eax ,相当于eax=eax-eax-CF。详细说明见下图11. |
x86 | |
Movapd ] |
移动对齐的压缩双精度浮点值。 | 从源操作数(第二个操作数)将包含两个压缩双精度浮点值的双四字移到目标操作数(第一个操作数)。此指令可用于将 128 位内存位置的内容加载到 XMM 寄存器、将 XMM 寄存器的内容存储到 128 位内存位置,或是在两个 XMM 寄存器之间移动数据。源操作数或目标操作数是内存操作数时,操作数必须对齐 16 字节边界,否则将生成一般保护性异常 (#GP)。 | x86 | |
setz |
把ZF标志的值传给指令后面跟着的一个字节型操作数,ZF=1时结果为1,ZF=0时结果为0 | 可以引申为条件指令集setCC |
x86 | |
fsub |
从目标操作数减去源操作数,差值存储到目标位置。目标操作数总是 FPU 数据寄存器(ST[0]-ST[1]);源操作数可以是寄存器或内存位置。内存中的源操作数可以是单精度实数、双精度实数、字整数或短整数格式。 | 无操作数版的指令从 ST(1) 寄存器的内容减去 ST(0) 寄存器的内容,结果存储到 ST(1)。单操作数版从 ST(0) 寄存器的内容减去内存位置的内容(实数或整数值),结果存储到 ST(0) 寄存器。双操作数版从 ST(i) 寄存器的内容减去 ST(0) 寄存器的内容,反之亦然。详细描述见图12 | x86 |
图1——
图2——
JCC系列指令:
测试标志位的JCC指令——
使用无符号数比较的JCC指令——
使用有符号数比较的JCC指令——
图3——
(1)
(2)与REP前缀一起使用时,Store String指令对初始化内存块很有用。例如,以下代码将BUFFER的100字节内存块初始化为0:
图4——关于repnz scasb
指令的解释
当repne scasb指令执行结束后,存在两种结束的可能;
一种是找到了空格字符,此时 ZF = 0;
另外一种是字符串中没有空格,当比较完最后一个字符是,仍不相等,此时ZF = 1;
所以repne scasb指令后面要跟踪jne指令,判断是哪一种情况;
当找到空格后,由于scasb指令自动修改地址, edi指向空格字符的下一个字符位置,所以空格字符的偏移地址是edi的值减1。
图5——
图6——
图7——
图8——
图9——
图10——
(1)
(2)
图11——
图12——