movzx 零扩展指令
movsx 符号扩展指令
LAHF 将EFLAGS寄存器的低字节复制到AH寄存器
SAHF 复制AH寄存器值到EFLAGS寄存器的低字节
XCHG 交换两个操作数的内容
INC 加1
DEC 减去1 Inc和dec不影响进位标志
NEG 取相反数,1变成-1(是-1的补码,计算机中用补码表示)
jmp 标号: 在PE文件中变成了相对地址,相对当前指令的偏移。
loop 首先ECX减去1,与0作比较,如果ECX!=0 则跳转到目的地址处。和jmp一样,在PE中,都是一个字节的相对地址,so,loop地址的范围[-128, 127]
enter numbytes,0=== push ebp; mov ebp, esp;sub esp, numbytes
leave === mov esp, ebp;pop ebp
ret num === ret add esp, num;
jmp 在16位下的地址在[127,-128]范围内,但在32位下是木有的
ja jb 无符号
jg jl 有符号
bt open, n将二进制第n位放入CF标志位中
arrayW WORD 1000h,2000h,3000h
mov eax, 0
mov ecx, LENGTHOF arrayW
lo:
mov ebx, ecx
dec ebx
mov ax, arrayW[ebx*TYPE arrayW]
call DumpRegs
loop lo
pushfd popfd 将EFLAGS标志寄存器放在或者拿出堆栈上。
1、mul
al*8位操作符 = ax
ax*16位操作符 = dx:ax
eax*32位操作符 = edx:eax
mul r/m8 16 32
乘积的高部分不为0的时候,设置CF,OF
执行完MUL指令后,检查进位标志,可以知道高半部分是否可以安全忽略
2、imul
al*8位操作符 = ax
ax*16位操作符 = dx:ax
eax*32位操作符 = edx:eax
如果乘积的上半部分不是低部分的符号扩展,CF,OF=1
注意:符号扩展不是符号 (符号扩展)(符号)(数据)
imul r16, r/m16
imul r16, imm8
imul r16, imm16
imul r32, r/m32
imul r32, imm8
imul r32, imm32
双操作数会根据操作数的大小剪裁乘积,如果有效位丢失,CF,OF=1
imul r16,r/m16,imm8
imul r16,r/m16,imm16
imul r32,r/m32,imm8
imul r32,r/m32,imm32
三操作数会根据操作数的大小剪裁乘积,如果有效位丢失,CF,OF=1
3、DIV
除之前,将相应的高位设置为0
被除数 除数 商 余数
ax r/m8 al ah
dx:ax r/m16 ax dx
edx:eax r/m32 eax edx
4、idiv
cbw al符号扩展至ax
cwd ax符号扩展至dx:ax
cdq eax符号扩展至edx:eax
在除法操作产生的商太大,目的操作数无法容纳的时候,导致除法溢出,会导致CPU中断,当前程序被终止。
乘法永远不可能产生溢出,但通过CF,OF判断高位是否是符号扩展。
5、adc,sbb
带CF加,带CF减
目的=目的+源+CF
目的=目的-源-CF
movsb movsw movsd 复制esi到edi寻址的内存地址处
cmpsb cmpsw cmpsd 相当于cmp [esi],[edi]!
scasb scasw scasd 扫描字符串,比较累加器(al,ax,eax)与edi寻址的内存地址处 cmp [al], [edi]
stosb 存储累加器的内容至edi内存地址处
lodsb 字符串数据装入累加器,加载esi寻址的内存地址处的内容至累加器
req 当ecx>0时重复
reqz reqe 当零标志置位并且ecx>0时重复
repnz reqne当零标志清零并且ecx>0时重复
req movsb执行movsb执行首先测试ecx>0?如果ecx=0,则执行下条指令,如果ecx>0,那么ecx=ecx-1,并且执行movsb
cld std清除、设置方向标志
cld,movs* esi=esi+type edi=edi+type
std, movs* esi=esi-type edi=edi-type
cld
req movsb
reqne cmpsb的顺序, 1.检测ZF标记,ZF=0执行2,ZF=1执行下一条指令 (第一次循环的时候不检测这一条)
2.ecx>0? ecx=0则执行下条语句,ecx>0那么ecx=ecx-1,并且执行3
3.cmp [edi],[esi],edi+type,esi+type
reqe scasb的顺序 1.检测ZF标记,ZF=1执行2,ZF=0则执行下一条指令(第一次循环的时候不检测这一条)
2.ecx>0? ecx=0则执行下一条指令,ecx>0那么ecx=ecx-1,并且执行3
3.al与[edi]做比较,设置ZF位,edi+type
req stosw 1.ecx>0? ecx=0则执行下一条,ecx>0则ecx=ecx-1并且执行2
2.mov [edi],ax,edi=edi+type
lodsb === mov al, [esi],inc esi
找到字符,在找到字符的+1;一直到最后的,在字符串最后一位+1
移位指令 reg, imm8
mem, imm8
reg, cl
mem ,cl
逻辑移位,高位补0
算术移位,高位补符号位
shl 逻辑左移 有无符号的快速乘法,作为有符号的时候,如果发生溢出会设置溢出标志。移出的最高位放入CF
shr 逻辑右移 无符号逻辑右移n位相当于该操作数除以2的n次方。移出的最低位放入CF
sal 算术左移 与shl是等价的。移出的最高位放入CF
sar 算术右移 有符号数的除法。移出的最高位放入CF,最高位补成符号位
rol 循环左移 将移动出的最高位同时放入CF和最低位
ror 循环右移 将移出的最低位同时放入CF和最高位
rcl 带进位的循环左移 将CF位看成数据的一部分,其他与rol一样
rcr 带进位的循环右移 将CF位看成数据的一部分,其他与ror一样
shld 双精度左移
shrd 双精度右移
SHLD reg/mem16/32,reg16/32,CL/imm8 这里的cl/imm8是 mod32的,所以 mod32相当于移位0位,目的操作数不变
在使用移位和一个循环指令对一个有符号整数移位一位后得到的值如果超出了该操作数能表示的有符号数的范围,那么溢出标志就会置位。即符号位发生变化,
移位位数大于1时,OF无意义。
sub esp, 4 mov [esp], eax == push eax 在进程进入入口执行时,进程的堆栈已经准备好,esp已经指向堆栈
在push ax push bx 的时候,是压入两个字节,没有push al pop al sub esp, 4
push 'c'自动扩展成4字节
pushad popad 压入所有的通用寄存器
无符号整数加减法和进位标志的关系
两个无符号整数相加,进位标志CF就是两者的进位;
两个无符号数相减,相当于被减数加上减数的补码,只有转一圈,产生进位了,其结果才是正确得无符号整数,因此进位标志是结果进位的相反数,计算结果进位为0,CF置位,计算结果进位为1,CF清空。
有符号整数加法和溢出标志的关系
因为有符号整数的减法可以变成加法,所以只考虑有符号加法就行。
两个正数相加为负数,两个负数相加为正数,则为溢出。
两个不同符号的整数相加,结果不可能溢出。
##:其实可以不关心这些东西,只要用JO,JC来判断结果就行了!!