汇编 | 条件码寄存器、二进制数加减规则、部分汇编指令[push、pop、cmp、jcondition等]

内容包括:条件码寄存器、二进制数加减规则、汇编指令[mov、call、push、pop、ret、add/sub、imul、cmp、shr/shl、lea、jmp、jcondition(jge、jle)]

一、条件码寄存器:描述最近算数或逻辑运算符操作结果的属性,存储值有1和0 , 1表示符合该属性,0表示不符合。

  • CF: Carry Flag(进/借位标志)    无符号数操作结果溢出(发生进位/借位)
  • ZF: Zero Flag(零标志)    结果为0
  • SF: Sign Flag(符号标志)    结果为负数
  • OF: Overflow Flag(溢出标志)    有符号数操作结果溢出(数据位高位和符号位高位 进位与否情况相同)

 CF是无符号操作数 操作结果的属性,OF是有符号操作数操作结果的属性

二、二进制数有符号数溢出、无符号数溢出举例:(后续学完硬件加法器的内容,再来详细梳理一下)

1. 有符号数:这里举例为1个字节的有符号数,范围为 -128 ~ 127,正数最大为0111 1111 即 2^7 - 1 = 127,负数最大为1000 0000 即 -2^7 = -128

  • 数据位高位进位,符号位未进位,溢出,如:0100 1111 + 0100 1010 =(0)1001 1001     [79 + 74 = -103](原来十进制数的结果往-128~127区间右边溢出
  • 数据位高位未进位,符号位进位,溢出,如:1000 0111 + 1000 0000 = (1)0000 0111  [(-121) +(-128)=  7]  (原来十进制数的结果往-128~127区间左边溢出
  • 数据位高位进位,符号位进位,不溢出,如:1111 1111 + 1100 0000 = (1) 1011 1111    [(-1) + (-64)= (-65)]
  • 数据位高位未进位,符号位未进位,不溢出,如:0000 1111 + 0000 1001 =(0) 0001 1000 (15 + 9 = 24)

注:括弧中为加法器进位,存储1个字节的内存空间或寄存器中的值只看后8位。

总结:

(1)溢出的情况就是两个大的正数相加,或两个大的负数相加(超过了当前符号数类型所能表示数的范围)。

(2)溢出发生时,数据位高位与符号位一个进位一个不进位。

(3)不溢出即两个小的负数相加,或两个小的正数相加,或一正一负相加。

(4)不溢出时,数据位高位与符号位 进位与否情况相同。

2. 无符号数:举例1个字节的无符号数,范围为0~255,即0000 0000 ~ 1111 1111

  • 借位如: 1000 0110 + 0000 1010=(0)1001 0000   [134 - 246 = 134+(-246)= 144] (原来十进制数的结果往0~255区间左边溢出)[做减法时,此时未发生进位C=0,CF=C^1,即C与1异或,因此CF=1]
  • 进位如:1000 0110 + 1111 0110 = (1)0111 1100   [134 + 246 = 124](原来十进制数的结果往0~255区间右边溢出)

 注:减法相当于取补码,-246即246的二进制取反加1后再进行运算。

 3. 无符号数、有符号数机器码的联系

如在8位字长的计算机中(即int类型空间为1字节):

  • 无符号数赋值给有符号数时,机器码相同:unsigned int x = 134;int   m = x,此时m和x的机器码均为86H即1000 0110B,只是最终表示的十进制值不同,无符号数表示的是134,有符号数表示的是-122。
  • 将两个无符号数各自赋值给两个有符号数,两个有符号数相加/减的机器码,与两个原来两个无符号数相加/减的机器码相同:unsigned int x = 134;int   m = x;unsigned int y = 246;int n = y;则x-y的机器码与m-n的机器码相同,均为90H=10010000B,其表示的十进制为多少,取决于接收结果的空间是int还是unsined类型 。 

三、mov指令:

将第二个操作数(寄存器的内容、内存中的内容或常数值)复制到第一个操作数(寄存器或内存),但不能用于直接从内存复制到内存

如:不能直接mov DWORD PTR[esp+32],DWORD PTR[esp+44]

必须 mov eax,DWORD PTR[esp+32]

        mov DWORD PTR[esp+44],eax      #利用临时寄存器来间接复制

(这里DWORD是4字节,ptr是pointer指针的缩写,可以理解为是临时的类型转换,相当于C语言中的强制类型转换。默认是word 2字节)

四、call指令

用于实现子程序(过程、函数等)的调用。

  • 如:_B:
  • (后面接B函数的操作)
  • 在A中调用B,即A函数里有 call _B

这个时候esp低地址会出现存储返回地址的空间。

如esp-4地址指向的空间存储返回地址,即存储A函数中call_B下一条语句的地址,以便ret时继续执行下一条语句。

这里要注意,A函数内部的变量,如果要传入B,如B(a,b),需要在A栈的栈顶存储传入的值,B中以ebp+8和ebp+12的形式去拿值(值传递的实现)。

五、push指令(改变esp位置)

压栈操作,将操作数压入内存的栈。

当A函数调用B函数时,B函数内部会有push语句,即

  • _B: 
  • push ebp
  • mov ebp,esp
  • sub esp,16        #这地方的16不是唯一值,可随情况变化

1. push ebp:

ebp寄存器中存储的是A函数的栈基地址,push ebp就是往低地址开一个空间,将ebp的内容存到这个空间,同时esp指向这个空间。

如调用函数B,A函数栈空间esp - 4存储了返回地址,此时需要再在esp - 8地址指向的空间存储ebp寄存器的内容,即esp - 8的空间存储A函数的栈基地址,再esp = esp - 8。

2. mov ebp,esp

原先ebp = A的栈基地址,现在ebp = esp,即将ebp指向存储了A栈基地址的空间,这样的目的是将ebp作为新函数的栈基地址。

3. sub esp,16

即esp = esp-16,esp作为新函数栈顶,而新函数栈空间大小即为16字节。

六、pop指令(改变esp位置)

出栈工作,esp地址指向空间中的内容出栈,esp值加4

如 pop ebp,即弹出栈顶元素到ebp,esp=esp+4

七、ret指令

实现子程序(过程、函数等)的调用及返回。

  • 如A调用了B,B函数执行完需要返回时,实际包含了
  • mov esp,ebp ,即esp = ebp ,esp从B函数栈栈顶,更改为指向A函数栈栈顶地址 - 8的位置。
  • pop ebp,即esp = esp+4,ebp = A函数栈基地址
  • 存储返回地址也pop掉,即esp = esp + 4,这样esp又指向原来A栈的栈顶,ebp指向A栈栈基。下一条语句的这个地址可能是用一个寄存器存储了(我猜测),当esp,ebp都复原后,再将PC=下一条语句的地址。

八、add/sub指令:

左右操作数相加/减,且结果放到左边操作数里,左边操作数可以是寄存器,也可以是内存空间。

九、imul指令:

带符号整数乘法指令,有两种格式:①两个操作数,将两个操作数相乘, 将结果保存在第一个操作数中,第一个操作数必须为寄存器;②三个操作数,将第二个和第三个操作数相乘,将结果保存在第一个操作数中,第一个操作数必须为寄存器。

十、cmp指令:

cmp用于比较两个操作数的值

  • 如:cmp dword ptr[var] ,10 即 var指向的内存空间里存储的值减去10,看结果的属性,从而设置条件码的值。
  • 如:cmp R1,R2 ,即R1-R2,若R1 = 5,R2 = 10,结果即为 -5 ,如果R1和R2是无符号数,CF=1,ZF=0,SF=1,OF不发生变化;如果R1和R2是有符号数,CF不发生变化,ZF=0,SF=1,OF=0。

 十一、shl/shr指令

shl为逻辑左移,shr为逻辑右移

  • 如:shl eax,1    将eax逻辑左移1位,相当于十进制数乘2的操作。

十二、lea指令:

地址传送指令,将有效地址传送到指定的寄存器

  • 如:mov DWORD PTR[esp+16],5  #把常量5放入栈顶指针偏移16个位置的地址指向的空间         lea eax,[esp+16]  #把这个地址再放入eax临时寄存器

十三、jmp指令:

 控制IP转移到<lable>所指示的地址。

  • 如:jmp <lable>
  • lable:...
  • 也可以jmp 地址

十四、jcondition指令:

条件转移指令:依据CPU状态一系列条件状态转移,即若条件码满足,就跳转到lable标签的语句。

  • jge<lable>(jump when greater than or equal to) 
  • 跳转条件:结果大于等于0,即SF = 0或ZF=1
  • jle<lable>(jump when lesss than or equal to)
  • 跳转条件:结果小于等于0,即SF = 1或ZF=1

  • 18
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值