cdq(Convert Double to Quad)
功能:
将 EAX 扩展为 64 位数 EDX:EAX。该指令先把edx的每一位置成eax的最高位(若eax>=0x80000000, 则edx=0xFFFFFFFF;若eax<0x80000000,则edx=0x00000000),再把edx扩展为eax的高位。
应用:
该指令常用于扩展被除数,很久前,指令集规定除数必须是被除数的一半长,这个规定一直被沿用。使用IDIV执行除法时,如果除数是32位,这就要求被除数是64位,即EDX:EAX,所以扩展一下EAX以满足除法指令的条件并且得到正确的结果。
movsx
功能:
带符号扩展传送指令。符号扩展的意思是,当计算机存储某一个有符号数时,符号位位于该数的第一位,所以,当扩展一个负数的时候需要将扩展的高位全赋为1.对于正数而言,符号扩展和零扩展MOVZX是一样的,将扩展的高位全赋为0。
应用:
mov bl,80h
movsx ax,bl
ax = 0FF80h
lea
功能:
取地址指令,主要用于动态内存定位。
应用:
int It001;
void main()
{
int It002;
........
}
全局变量IT001的寻址操作一般会被翻译成 mov eax,offset It001;局部变量It002的寻址操作只可能被翻译成LEA eax,[ebp - 8]。
因为全局变量的地址时编译器可知的,所以它直接被优化了。而局部变量的地址直到程序运行才能被识别,所以必须用LEA指令寻址。
总结: lea当寄存器为esp或esi或edi时是求内存单元地址,否则是计算表达式
ptr
功能:
数据类型转换。
应用:
格式:类型 PTR 变量 说明:类型可以是BYTE, WORD, DWORD
1) 源和目的操作数类型应该相同,如果数据段中数据类型与源或目的操作数类型不同,则应该进行类型转换。
2) 没有寄存器参与的内存单元访问指令中,用PTR显示指明内存单元的长度。
mov word ptr ds:[0],1
rep movsd
功能:
若ecx != 0,便执行rep movsd,即mov ds:edi , es:esi ecx = ecx - 1.
应用:
以下代码是把Str2的前12h个元素赋值给Str1.
mov ecx,12h
mov esi, offset Str2
lea edi, offset Str1
rep movsd
rep stosd
功能:
若 ecx != 0,便执行rep stosd,即mov es:di , eax ecx = ecx – 1.
应用:
以下代码是给以es:edi为起始地址的E7h个元素赋0.
mov ecx, 0E7h
xor eax, eax
lea edi, [ebp+var_1]
rep stosd
shl/shr/sal/sar
功能:
shl(Shift Left): 逻辑左移
shr(Shift Right): 逻辑右移
sal(Shift Arithmetic Left): 算术左移
sar(Shift Arithmetic Right): 算术右移
规则:
shl/sal: 每位左移, 低位补 0, 高位进 CF
shr: 每位右移, 低位进 CF, 高位补 0
sar: 每位右移, 低位进 CF, 高位补符号位
它们的结果影响 OF、SF、ZF、PF、CF
idiv/div指令
优化成乘法和移位。
1)a/10 = (a*0x66666667)>>34
0x66666667 ->1717986919
2的34次方 ->17179869184
MOV EAX,66666667
IMUL ECX
SAR EDX,2
MOV EAX,EDX
SHR EAX,1F
通过imul指令进行乘法运算后,高位存在edx中,低位存在eax中,结果为[edx][eax]。SAR EDX,2
指令将EDX算术右移2位,相当于将运算结果右移32+2位;SHR EAX,1F
将EAX逻辑右移31位,相当于将EAX作为有符号数清零。
2)a/100 =(a*0x51EB851F)>>37
0x51EB851F ->1374389535
2的37次方 -> 137438953472
MOV EAX,51EB851F
IMUL ECX
SAR EDX,5
MOV EAX,EDX
SHR EAX,1F