您的位置:首页 > 其它

汇编指令

2016-07-28 17:54 274 查看
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来判断结果就行了!!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: