汇编指令的积累

实践过程中的一些汇编指令及含义的积累。

指令 含义 补充 指令系统
cbwcwdcdqcwdecdqe 符号拓展指令 见图1
sidt 存储全局/中断描述符表格寄存器 将全局描述符表格寄存器 (GDTR) 或中断描述符表格寄存器 (IDTR) 中的内容存储到目标操作数。示例见图2. x86
JCC 汇编跳转指令 详细描述见下 x86
STOSSTOSBSTOSWSTOSD 字符串存储指令 详细说明见图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,BXAND 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
sarshr 汇编语言中SAR和SHR指令都是右移指令,SAR是算数右移指令(shift arithmetic right),而SHR是逻辑右移指令(shift logical right) 两者的区别在于SAR右移时保留操作数的符号,即用符号位来补足,而SHR右移时总是用0来补足;例如10000000算数右移一位是11000000,而逻辑右移一位是01000000 x86
MovsxMovsxd 符号扩展指令 符号扩展/传送指令有两大类: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系列指令:

  1. 测试标志位的JCC指令——

  2. 使用无符号数比较的JCC指令——

  3. 使用有符号数比较的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——