实验三 循环程序设计

实验三 循环程序设计

一、实验目的

1. 掌握 loop 指令。

2. 掌握while和do while循环结构。

3. 掌握伪指令.while和 .repeat。

4. 掌握一维数组处理的常用算法。

二、实验内容

1.有一个首地址为array的10个有符号的双字数组,编程分别求出偶数和与奇数和并输出。

偶数和:
include vcIO.inc
include io32.inc
.data  
	array dword 12,34,123,78,43,234,79,86,98,20
	esum  dword ?
.code
start:
	mov ecx,lengthof array
	xor eax,eax
	mov esi,eax
again: 
	mov ebx,array[esi*4]
	test ebx,1
	jnz next
	add eax,ebx
next: 
	inc esi
	loop again
	mov esum,eax
	call dispuid
exit 0
end start
奇数和:
include vcIO.inc
include io32.inc
.data  
	array dword 12,34,123,78,43,234,79,86,98,20
	esum  dword ?
.code
start:
	mov ecx,lengthof array
	xor eax,eax
	mov esi,eax
again: 
	mov ebx,array[esi*4]
	test ebx,1
	jz next
	add eax,ebx
next: 
	inc esi
	loop again
	mov esum,eax
	call dispuid
exit 0
end start

思考题:将求和改为求(1)最大值与最小值 (2)正数和与负数和 (3)素数和

最大值与最小值
include vcIO.inc
include io32.inc
.data  
	msg1 byte '输出最大值',10,0
	msg2 byte '输出最小值',10,0
	fmts byte '%s',0
	fmtd byte '%d',10,0
	array dword 12,34,123,78,43,234,79,86,98,20
	max dword ?
	min dword ?
.code
start:
	mov ecx,lengthof array -1
	mov eax,array[0]
	mov ebx,eax
	mov esi,1
	.while(ecx!=0)
		cmp eax,array[esi*4]
		jge small
		mov eax,array[esi*4]
	small:
		cmp ebx,array[esi*4]
		jle next
		mov ebx,array[esi*4]
	next:
		inc esi
		dec ecx
	.endw
	mov max,eax
	invoke printf,offset fmts,offset msg1
	invoke printf,offset fmtd,max
	mov min,ebx
	mov eax,ebx
	invoke printf,offset fmts,offset msg2
	invoke printf,offset fmtd,min
exit 0
end start
正数和与负数和
include io32.inc
.data
array sdword -4,-2,-1,-6,-5,0,1,2,1,4,5
sum_gz sdword 0
sum_lz sdword 0
msg_gz byte '正数和=',0
msg_lz byte '负数和=',0
.code
main:
	mov ecx,lengthof array-1
	xor eax,eax  ;sum_gz
	mov ebx,eax  ;sum_lz
	mov esi,eax
	;在使用伪代码时,如果存在负数,则有必要加上 sdword ptr
	.while sdword ptr ecx>=0
	   mov edx,array[esi*4]
	   .if sdword ptr edx>0
	   add eax,edx
	   .endif
	   .if sdword ptr edx<0
	   add ebx,edx
	   .endif
	   inc esi
	   dec ecx
	.endw
	mov sum_gz,eax
	mov eax,offset msg_gz
	call dispmsg
	mov eax,sum_gz
	call dispsid
	call dispcrlf
	mov sum_lz,ebx
	mov eax,offset msg_lz
	call dispmsg
	mov eax,ebx
	call dispsid
exit 0
end main
素数和
include io32.inc
include vcio.inc
.data
	array dword 1,4,-2,3,-1,5,7,-3,0,2
	primeSum dword 0 ;素数和
	msg byte '素数和为',0
.code
start:
	mov ecx,lengthof array
	mov esi,0
	again:
		mov eax,array[esi*4]
		cmp eax,0
		jle next ;判断是否是素数
		cmp eax,1
		je sum
		jmp isPrime ;非无符号数,下一个
	isPrime:
		mov ebx,2
		.while ebx<eax
			xor edx,edx
			div ebx
			cmp edx,0
			jz next
			inc ebx
		.endw
		sum:
			mov eax,array[esi*4]
			add primeSum,eax
	next:
		inc esi
	loop again
	mov eax,offset msg
	call dispmsg
	mov eax,primeSum
	call dispsid
exit 0
end start

2.有一个首地址为array的10个有符号的双字数组,编程逆置数组并输出。

include io32.inc
.data
array dword 10,11,9,8,7,6,3,1
count equ lengthof array
.code
main:
	mov esi,0
	mov edi,count-1
	.while(esi<edi)
		mov eax,array[esi*4]
		xchg eax,array[edi*4]
		mov array[esi*4],eax
		inc esi
		dec edi
	.endw
	mov ecx,count
	mov esi,0
	again:
		mov eax,array[esi*4]
		call dispsid
		call dispcrlf
		inc esi
		dec ecx
		jnz again
exit 0
end main

3. Fibonacci numbers的定义: f1=1,f2=1, fn= fn-1 + fn-2 n>=3 编程输出Fibonacci numbers的前30项。

include vcIO.inc
include io32.inc
.data  
	fmtc byte 10,'counter=%6u',0
	fmt byte '%10u',0
.code
main proc
	invoke  printf,offset fmt,1
	invoke printf,offset fmt,1
	mov ecx,2
	mov esi,1
	mov edi,esi
 again:
    add esi,edi
	pushad
	invoke printf,offset fmt,esi
	popad
	cmp ecx,31
	je over
	inc ecx
	xchg esi,edi
	jmp again
 over:
    dec ecx
    invoke printf,offset fmtc,ecx
 ret
main endp
end main
思考题:在不产生溢出的情况下n的最大值是多少?
include vcIO.inc
include io32.inc
.data  
	fmtc byte 10,'counter=%7u',0
	fmt byte '%10u',0
.code
main proc
	invoke  printf,offset fmt,1
	invoke printf,offset fmt,1
	mov ecx,2
	mov esi,1
	mov edi,esi
 again:
    add esi,edi
	jc over
	inc ecx
	pushad 
	   invoke printf,offset fmt,esi
	popad
	xchg esi,edi
	jmp again
 over:
    invoke printf,offset fmtc,ecx
 ret
main endp
end main

4.编程写一个完整的程序,求出2012年~2099年中的所有闰年年份,存入Lyear数组中,并输出所有闰年。(可考虑控制每行输出5个年份)提示:采用伪代码描述如下:

esi=0 ;闰年个数计数器;
ecx=2012 ;年份计数器;
while (ecx<2100)
{
if (year mod 4=0 and year mod 100 <>0) or (year mod 400=0) then
{ Lyear[esi]=ecx; //Lyear[esi] 为存放闰年的数组
esi++;}
ecx++;
}
Lcounter=esi ;Lcounter 闰年个数

include vcIO.inc
include io32.inc
.data  
	year dword ?
	lyear dword 100 dup(?)
.code
main proc
	mov esi,0
	mov year,2012
	.while year<=2099
	mov eax,year
	xor edx,edx
	mov ebx,400
	div ebx
	cmp edx,0
	jz leap
	mov eax,year
	xor edx,edx
	mov ebx,4
	div ebx
	cmp edx,0
	jnz noleap
	mov eax,year
	xor edx,edx
	mov ebx,100
	div ebx
	cmp edx,0
	jz noleap
leap:
	mov eax,year
	call dispuid
	call dispcrlf
	mov lyear[esi*4],eax
	inc esi
noleap:
	inc year
.endw
ret
main endp
end main

5.有一个首地址为string的字符串 ,分别统计string中空格、大写英文字母的个数并输出。

include vcIO.inc
include io32.inc
.data  
	msg byte 'ab efg AB 12 !@#',10,0
	space dword ?
	lowercase dword ?
	fmtstr byte '空格=%d 小写字母=%d',10,0
.code
main proc
	mov ecx,lengthof msg-1
	xor eax,eax
	mov ebx,eax
	mov esi,offset msg
again:
	mov dl,[esi]
	cmp dl,' '
	jnz letter
	inc eax
letter:
	cmp dl,'a'
	jb next
	cmp dl,'z'
	ja next
	inc ebx
next:
	inc esi
	loop again
	mov space,eax
	mov lowercase,ebx
	invoke printf ,offset fmtstr,eax,ebx

	ret
main endp
end main
思考题:还可继续统计空格、小写英文字母、数字和其它字符的个数并输出。

6. palindrome(回文)是指正读和反读都一样的数或文本。例如:11、121、12321等,编写程序,求10到10000之间所有回文数并输出。要求每行输出10个数。( 提示:采用div指令把整数分解为单个的数字,并将它们组合成一个新的整数。)

include vcIO.inc
include io32.inc
.data  
	msg byte 13,10,0
	fmts byte '%s',0
	fmtd byte '%7d',0
.code
main proc
	mov edi,0
	mov ecx,10
	mov ebx,ecx
	.while ecx<=10000
		xor esi,esi
		mov eax,ecx
		.while(eax!=0)
			xor edx,edx
			div ebx
			imul esi,10
			add esi,edx
		.endw
		cmp esi,ecx
		jne next
		mov eax,ecx
		pushad
		 invoke printf,offset fmtd,eax
		popad
		inc edi
		.if edi==10
		 pushad
		  invoke printf,offset fmts,offset msg
		  popad
		  mov edi,0
		  .endif
		  next:
			inc ecx
		.endw
		ret
main endp
end main
思考题:测试一字符串是否为“回文串”。

7. 有一个首地址为string 的字符串,剔除string 中所有的空格字符。请从字符串最后一个字符开始逐个向前判断、并进行处理。

include vcIO.inc
include io32.inc
.data
   string byte ' i love huibian ,and you?',0
   fmtd byte '%s'
.code
start:
	mov esi,lengthof string-1
	mov edi,lengthof string-1
	.while sdword ptr esi>=0
		cmp string[esi],20h
		jnz next
		inc esi
		mov ebx,esi
		.while ebx<=edi
		mov al,string[ebx]
		mov string[ebx-1],al
		inc ebx
		.endw
		dec edi
	next:
		dec  esi
	.endw
		mov byte ptr string[edi+1],0
		mov eax,offset string
		call dispmsg
	exit 0
end start

三、回答问题:

1. 在循环结构中,如何避免无限循环情况的发生?

使用确定循环条件真能结束的条件,如不能保证假定的循环结束条件是否真能发生,则应设置循环次数,在汇编语言的loop指令中中,一般设置eax>0。

2. 下面的程序段中,循环体将被执行多少次?如果的初值为-100,循环体将被执行多少次?

		mov	ecx,0
loopTest:	mov	eax,ecx
		call	dispuid
		loop	loopTest

当前循环体,ecx为零,循环体循环;当ecx为-100时,循环体被执行的次数为

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值