钱晓捷《32位汇编语言程序设计》第四章习题与代码解析

4.15 EAX符号扩展到EDX

IA-32处理器的指令CDQ将EAX符号扩展到EDX。假若没有该指令,编程实现该指令功能。

(1)按照符号扩展的含义编程,即:EAX最高为0,则EDX=0;EAX最高为1,则EDX=FFFFFFFFH。
程序代码:

			include io32.inc
			.data
plmsg		byte 'Input Number:' ,13,10,0	
			.code
start:		mov eax,offset plmsg
			call dispmsg
			call readhd
			test eax, 80000000h		;测试最高位
			jz next				;最高位为0,跳转
			mov edx,0ffffffffh	
			jmp done
next:		mov edx,0
done :		call dispcrlf
			mov eax,edx
			call disphd
			exit 0
			end start

运行结果:
在这里插入图片描述

(2)使用移位等指令进行优化编程。
法一:
解题思路:算数右移31位直接将符号位复制31次:

  	mov edx,eax
  	sar edx,31			;算数右移31位相当于将eax最高位复制31次

程序代码:

			include io32.inc
			.data
plmsg		byte 'Input Number:' ,13,10,0	
			.code
start:		mov eax,offset plmsg
			call dispmsg
			call readhd
			mov edx,eax
			sar edx,31			;算数右移31位相当于将eax最高位复制31次
done :		call dispcrlf
			mov eax,edx
			call disphd
			exit 0
			end start

运行结果:
在这里插入图片描述
法二:
解题思路:将eax最高位移出来给edx,edx再复制32次:
程序代码:

			include io32.inc
			.data
plmsg		byte 'Input Number:' ,13,10,0	
			.code
start:		mov eax,offset plmsg
			call dispmsg
			call readhd
			mov edx,eax
			rol	eax,1			;将eax最高位移出至CF
			rcl	edx,1			;将最低位移出,CF进入最高位
			sar	edx,31		;将此时的最高位复制31次
			rcr eax,1		;将CF中储存的数据归还给eax
done :		call dispcrlf
			call disphd
			exit 0
			end start

运行结果:
在这里插入图片描述

4.17 输入输出0~9数字

编写一个程序,先提示输入数字“Input Number:0~9”,然后在下一行显示输入的数字,结束;如果不是键入了0~9数字,就提示错误“Error!”,继续等待输入数字。

解题思路:分支结构比较一下即可:
程序代码:

			include io32.inc
			.data
plmsg		byte 'Input Number:0~9:',13,10,0	;输入提示信息
ermsg		byte 'Error!',13,10,0		;错误信息
			.code
			mov eax, offset plmsg
			call dispmsg			
start:		call readuib		;输入一个无符号8位十进制数
			cmp eax,0			;0比较
			jb no				;小于0,跳转
			cmp eax,9			;9比较
			ja no				;大于9,跳转
			jmp done
no:			mov eax, offset ermsg
			call dispmsg			
			jmp start			;继续输入	
done: 		exit 0
			end start

运行结果:
在这里插入图片描述

4.29 素数判断程序

编写一个程序,提示用户输入一个数字,然后显示信息说明该数字是否是素数。素数(Prime)是只能被自身和1整除的自然数。

解题思路:循环加分支,注意每步除法前eax要归值,edx要归零
程序代码:
(1)采用直接简单的算法:假设输入N,将其逐个除以2~N-1,只要能整除(余数为0)说明不是素数,只有都不能整除才是素数。

			include io32.inc
			.data
plmsg		byte 'Input an integer:' ,13,10,0	
findmsg		byte 'Prime : ',0
nomsg  		byte 'Prime not!',13,10,0
errmsg		byte 'Input Error!',0
			.code
start:		mov eax,offset plmsg
			call dispmsg
			call readuid
			cmp eax,0
			jz err				;输入值等于0,error
			cmp eax,3				;分支结构解决输入为12的情况
			jb prime
			mov ecx,eax				;初始化循环起始值
			mov ebx,eax				;定义被除数
			dec ecx
again:		
			mov edx,0
			mov eax,ebx				;复原eax
			div ecx					;edx.eax / ecx 					
			test edx,edx			;edx 存余数,eax存商
			jz	noprime				;余数若为0,该数不是素数,跳转
			dec ecx					;ecx自减
			cmp ecx,1			
			jz 	prime				;循环正常结束,该数是素数
			jmp again				;持续遍历至整数2,停止
prime:				
			mov eax, offset findmsg	
			call dispmsg
			mov eax,ebx								
			call dispuid			;显示该素数
			jmp done
noprime:	mov eax, offset nomsg	
			call dispmsg
			jmp done
err:		mov eax, offset errmsg	
			call dispmsg		
done:		exit 0
			end start

运行结果:在这里插入图片描述

(2)采用只对奇数整除的算法:1、2和3是素数,所有大于3的偶数不是素数,从5开始的数字只要除以从3开始的奇数,只有都不能整除才是素数。
解题思路:利用分支结构,先判断1,2,3的情况,后判断大于3的偶数的情况,再判断大于3的奇数的情况,注意div之前edx要清零,eax要还原。
程序代码:

			include io32.inc
			.data
plmsg		byte 'Input an integer:' ,13,10,0	
findmsg		byte 'Prime : ',0
nomsg  		byte 'Prime not!',13,10,0
errmsg		byte 'Input Error!',0
			.code
start:		mov eax,offset plmsg
			call dispmsg
			call readuid
			cmp eax,0
			jz err					;输入值等于0,error
			cmp eax,4				;1,2,3都是素数
			jb prime
			mov edx,0
			mov ebx,eax 			
			shr ebx,1				;右移除以2看余数
			jnc	noprime				;余数若为0,为偶数,该数不是素数,跳转
			mov ecx,3				;初始化循环起始值
			mov ebx,eax				;定义被除数
again:		
			mov edx,0
			mov eax,ebx				;复原eax
			div ecx					;edx.eax / ecx 					
			test edx,edx			;edx 存余数,eax存商
			jz	noprime				;余数若为0,该数不是素数,跳转
			add ecx,2				;ecx自增2,3开始的奇数
			cmp ecx,ebx			
			jz 	prime				;循环正常结束,该数是素数
			jmp again				;持续遍历至整数2,停止
prime:				
			mov eax, offset findmsg	
			call dispmsg
			mov eax,ebx								
			call dispuid			;显示该素数
			jmp done
noprime:	mov eax, offset nomsg	
			call dispmsg
			jmp done
err:		mov eax, offset errmsg	
			call dispmsg		
done:		exit 0
			end start

运行结果:
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值