Win32汇编系列五、分支结构程序设计

前言

程序不可能完全的顺序去执行,有时候我们会使用选择、循环结构去设计,本章记录汇编中的选择结构程序设计,也就是学习条件转移指令,在Win32汇编中有两种方式根据条件执行不同的逻辑,第一种是条件转移指令,这类指令根据标志位的值进行跳转,另一种是.IF、.ELSE等伪指令。

条件转移指令

条件转移指令就是根据测试的条件是否满足,如果满足,则进行转移,条件测试指令测试标志寄存器中一个或多个标志是否满足要求,如果满足要求,则控制转移到目的地址,如果不能满足要求,CPU就忽略条件转移指令并顺序执行,比如,在逻辑左移指令执行后,可以测试CF标志位判断操作数移出的最高位是否为1。

示例JZ

JZ指令就是当ZF标志位等于1时跳转,ZF标志位是运算结果位0时该标志位等于1,否则为0。

在下面代码中,TEST按逻辑与运算,8 AND 7结果位0,那么ZF标志位为1,紧跟后面的jz 就会发生跳转,如果8 AND 8时,结果不为0,所以ZF为0,所以不跳转。

.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
szOutFmt1 byte '未跳转',10,13,0
szOutFmt2 byte '跳转',10,13,0
.code

x dword 5
START:
	mov eax,8
	test eax,7
	jz Exit
	invoke printf,addr szOutFmt1
	invoke system ,addr szPause
	Exit:
	invoke printf,addr szOutFmt2
	invoke system ,addr szPause
END START

在这里插入图片描述

.IF 伪指令

我们也可是使用高级语言中类似的IF、ELSE来实现,这种方法更简单,更直观,主要是以前都要先执行一条能影响这些指令关心的标志位的指令,这样我们就必须要知道哪些指令能影响这些标志位,所以MASM汇编器就提供了.IF类似高级语法的伪指令。

下面是判断eax寄存器中如果值为8,那么输出为等于,否则输出不等于,当然我们可以加入.ELSEIF在进一步判断。

.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
szOutFmt1 byte '等于',10,13,0
szOutFmt2 byte '不等于',10,13,0
.code

x dword 5
START:
	mov eax,8
	.if eax == 8 
		invoke printf,addr szOutFmt1
		invoke system ,addr szPause
	.else
		invoke printf,addr szOutFmt2
		invoke system ,addr szPause		
	.endif

	
	Exit:

END START

在这里插入图片描述

表达式操作符

eq(等于) 、ne(不等于)、 gt(大于)、 lt(小于 )、 ge(大于等于 ) 、le(小于等于)这六个比较操作符用来比较两个常数,如果比较结果为真,则返回-1,否则返回0。但是这些不能用于比较寄存器或者内存变量,否则会出现编译错误。

除此之外还有常见的==、!=、>等比较方式,这些可以比较寄存器和内存变量值,但是MASM规定操作符左边只能是变量或是寄存器,操作符的两边不能同时为变量,但可以同时为寄存器。

.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
szOutFmt1 byte '等于',10,13,0
szOutFmt2 byte '不等于',10,13,0
.code

x dword 5
START:
	mov eax,8
	.if 8 eq 8
		invoke printf,addr szOutFmt1
		invoke system ,addr szPause
	.else
		invoke printf,addr szOutFmt2
		invoke system ,addr szPause		
	.endif
	Exit:
END START

在这里插入图片描述

还有CARRY?、OVERFLOW?、PARITY?、SIGN?、ZERO?操作符,这五个操作符分别代表标志寄存器里的五个标志位,也就是进位位、溢出位(CF)、奇偶位(PF)、符号位(SF)、零位(ZF)。

下面是示例符号位,符号位是SF标志,结果为负数时,SF等于1,否则为0。

首先将寄存器中原有的8减去9,结果肯定是负数,所以SF等于1,那么.if SIGN?就是TRUE,否则执行.else。

.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
szOutFmt1 byte '是',10,13,0
szOutFmt2 byte '否',10,13,0
.code

x dword 5
START:
	mov eax,8
	sub eax, 9
	.if SIGN?
		invoke printf,addr szOutFmt1
		invoke system ,addr szPause
	.else
		invoke printf,addr szOutFmt2
		invoke system ,addr szPause		
	.endif
END START

在这里插入图片描述

实例

  1. 输入两个整数,输出第一个数和第二个数关系.
.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
scanf  PROTO C : dword,:vararg
.data
inputFmt byte '%d%d',0
szPause db 'pause',10,13,0
szOutFmt1 byte '%d>%d',10,13,0
szOutFmt2 byte '%d<%d',10,13,0
szOutFmt3 byte '%d=%d',10,13,0
one dword 0
two  dword 0
.code


START:
		
		invoke scanf,addr inputFmt,addr one, addr two
		
		mov eax,one
		mov ebx,two
		.if eax>ebx
			invoke printf,addr szOutFmt1,eax,ebx
		.elseif eax<ebx
			invoke printf,addr szOutFmt2,eax,ebx
		.elseif  eax==ebx
			invoke printf,addr szOutFmt3,eax,ebx
		.endif
	
		invoke system ,addr szPause		

END START

在这里插入图片描述

  1. 输入一个小写字符,把他转化成大写,如果输入的不是小写字符,则输出"输入错误"。
.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
scanf  PROTO C : dword,:vararg
.data
x byte ?
inputFmt BYTE '%c',0
szPause db 'pause',10,13,0
szOutFmt1 byte '%c',10,13,0
szError byte '输入错误',10,13,0
.code


START:
	invoke scanf,addr inputFmt,addr x
	
	cmp x,'A'
	JB EXIT
	cmp x,'Z'
	JB EXIT
	sub x,32
	invoke printf,addr szOutFmt1,x
	invoke system,addr szPause		

	EXIT:

	invoke printf,addr szError
	invoke system,addr szPause	

END START

在这里插入图片描述
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值