Win32汇编系列三、整数算数运算符

整数算数运算指令也就是进行加、减、乘、除,相应的指令就是ADD、SUB、MUL、DIV,操作数可以是8位、16位、32位的。

标志寄存器

标志寄存器又称程序状态字,主要用于反映处理器的状态和ALU运算结果的某些特征及控制指令的执行,有些指令的执行会改变标志位,就比如逻辑运算指令等,不同的指令会影响不同的标志位。

每个标志位具体什么意思,本章就不说了。
在这里插入图片描述

如上面的PF,反应了运算结果中1的个数的奇偶性,如果个数为偶数,那么PF位位1,否则为0,还有如ZF反应了运算结果是否为0,如果为0,那么ZF位位1,否则为0,后面的例子会举例说明。

ADD

ADD是加法指令,用于源操作数加上目的操作数,最终结果存到源操作数中,ADD对于高级语言的语法就是a+=x,格式如下:

ADD Reg/Mem,Reg/Mem/Imm

Reg表示寄存器,英文Register的缩写,Mem表示内存,Imm表示立即数。

.386
.Model Flat, StdCall
Option Casemap :None

include	C:\masm32\include\kernel32.inc	
includelib	C:\masm32\lib\kernel32.lib	
includelib	C:\masm32\lib\msvcrt.lib


printf    PROTO C : dword,:vararg
system   PROTO C : dword,:vararg
.data
szMessage db 'a',10,13,0
bTest1 dword -1
szPause db 'pause',10,13,0
szOutFmt byte '%d+%d=%d',10,13,0
.code

START:
	mov eax,10
	
	add eax,10
	
	invoke printf,addr szOutFmt,10,10,eax
	invoke system ,addr szPause
END START

在这里插入图片描述

值为20的话,那么二进制就是0001 0100,标志位PF的值就是就是1,因为有两个1,是偶数,而ZF位由于结果不为0,就等于0。

我们可以通过OLLYDBG查看。
在这里插入图片描述

在换一下,计算3+4、0+0的值。

mov eax,3
add eax,4
invoke printf,addr szOutFmt,3,4,eax

由于结果为7,有3个1,是奇数,则PF位0,ZF位由于结果不为0,就等于0.

在这里插入图片描述

0+0=0,0也是偶数,所以则PF位1,ZF由于结果等于0,所以为1。

在这里插入图片描述
好了,真TM的绕。

加法还有一个INC指令,相当于高级语言的a++,就是实现操作数+1,还有两个有关的指令是ADC、XADD。

减法

减法指令是SUB,将源操作数值减去目的操作数,结果存放到源操作数。

SUB Reg/Mem,Reg/Mem/Imm

受影响的标志位有AF、CF、OF、PF、SF、ZF

加法有单独加1的指令,当然减法也有,也就是DEC,还有两个有关的指令是SBB、NEG。

.386
.Model Flat, StdCall
Option Casemap :None

include	C:\masm32\include\kernel32.inc	
includelib	C:\masm32\lib\kernel32.lib	
includelib	C:\masm32\lib\msvcrt.lib


printf    PROTO C : dword,:vararg
system   PROTO C : dword,:vararg
.data
szMessage db 'a',10,13,0
bTest1 dword -1
szPause db 'pause',10,13,0
szOutFmt byte '%d-%d=%d',10,13,0
.code

START:
	mov eax,123H
	
	SUB eax,122H
	
	invoke printf,addr szOutFmt,123H,122H,eax
	invoke system ,addr szPause
END START

在这里插入图片描述

乘法

32 位模式下,MUL(无符号数乘法)指令有三种类型:
1、 第一种执行 8 位操作数与 AL 寄存器的乘法;
2、第二种执行 16 位操作数与 AX 寄存器的乘法;
3、第三种执行 32 位操作数与 EAX 寄存器的乘法。

乘法指令一般仅乘数在指令中显示的写出来,而被乘数固定用EAX,结果存放在EDX|EAX中。

乘法影响的标志位有CF、OF。

.386
.Model Flat, StdCall
Option Casemap :None

include	C:\masm32\include\kernel32.inc	
includelib	C:\masm32\lib\kernel32.lib	
includelib	C:\masm32\lib\msvcrt.lib


printf    PROTO C : dword,:vararg
system   PROTO C : dword,:vararg
.data
szMessage db 'a',10,13,0
bTest1 dword -1
szPause db 'pause',10,13,0
szOutFmt byte '%d*%d =%d',10,13,0
.code

x dword 5
START:
	mov eax,8
	mul x
	invoke printf,addr szOutFmt,8,x,eax

	invoke system ,addr szPause
END START

在这里插入图片描述
MUI是无符号乘法,有符号乘法指令是IMUL。无符号乘法指令数据的最高位是作为“数值”参与运算,有符号指令数据高位是作为“符号位”运算。

除法

除法也分无符号DIV和有符号IDIV,除法指令仅除数在指令中显示的写出来,被除数固定EDX|EAX,商存在EAX中,余数在EDX中。

受影响的标志位AF、CF、OF、PF、SF、ZF

.386
.Model Flat, StdCall
Option Casemap :None

include	C:\masm32\include\kernel32.inc	
includelib	C:\masm32\lib\kernel32.lib	
includelib	C:\masm32\lib\msvcrt.lib


printf    PROTO C : dword,:vararg
system   PROTO C : dword,:vararg
.data
szMessage db 'a',10,13,0
bTest1 dword -1
szPause db 'pause',10,13,0
szOutFmt byte '%d/%d =%d...%d',10,13,0
.code

x dword 5
START:
	mov eax,18
	cdq
	idiv x
	invoke printf,addr szOutFmt,18,x,eax,edx

	invoke system ,addr szPause
END START

在这里插入图片描述

为什么在使用DIV指令之前EDX应该为0?

从上面发现一条指令cdq,如果没有这条指令,程序会出错,这条指令的意思是将EAX符号位填充到EDX,也就是说,如果EAX小于十六进制80000000H,那么EDX就会成为0,如果大于十六进制80000000H,那么EDX就全是F。

也就是运算DIV指令之前EDX应该为0,关于这个问题,我找到一篇很好的文章。

https://www.codenong.com/38416593/

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值