微机原理汇编编程题期末复习用

题目总览

在这里插入图片描述

常用指令

指令含义
add加法
inc增1
sub减法
dec减1
cmp比较
xor逻辑异或
test测试

题目

1.输入一个数,判断奇、偶数。

include io32.inc
.data
	isOdd byte '此数为奇数',0
	isEven byte '此数为偶数',0
.code
start:
	call readuid
	shr eax,1
	jc odd
	mov eax,offset isEven
	jmp display
odd:
	mov eax,offset isOdd
display:
	call dispmsg
exit 0
end start

2.将下面C语言程序的代码片段转换为功能等价的汇编语言代码;编写完整的汇编语言程序验证转换的正确性,其中sign与sinteger均为双字变量。
if (sinteger == 0)
 sign = 0;
else if ( sinteger> 0)
 sign = 1;
else
 sign = -1;

include io32.inc
.data
	sinteger dword ?
	sign dword ?
.code
start:
	call readsid
	mov sinteger,eax
	cmp sinteger,0
	jz isZero
	jmp notZero
isZero:
	mov eax,0
	mov sign,eax
	jmp display
notZero:
	jl less
	jmp greater
less:
	mov eax,-1
	mov sign,eax
	jmp display
greater:
	mov eax,1
	mov sign,eax
	jmp display
display:
	mov eax,sign
	call dispsid
exit 0
end start

3.编写程序,计算下面函数的值并输出。
在这里插入图片描述

include io32.inc
.data
	x dword ?
.code
start:
	call readsid
	mov x,eax
	cmp x,0
	jl lessZero
	jmp greaterZero

	lessZero:
		imul eax,2
		jmp display

	greaterZero:
		cmp x,10
		jle lessTen
		jmp greaterTen

		lessTen:
			imul eax,3
			jmp display

		greaterTen:
			imul eax,4
			jmp display

	display:
		call dispsid
exit 0
end start

4.输入一个年份(可调用readuid子程序,读入年份),判断是否是闰年。
提示:采用伪代码描述如下:
read year
if (year mod 4=0 and year mod 100不等于0) or (year mod 400=0) then
 print year ,'is leap year. ’
else
 print year ,'is not leap year. ’

include io32.inc
.data
	year dword ?
	isLeap byte '是闰年',0
	notLeap byte ' 不是闰年',0
.code
start:
	call readuid 
	mov year,eax
	call dispuid ;输出年份
	xor edx,edx ;置零
	mov ebx,400
	div ebx ;被除数:eax
	cmp edx,0 ;余数:edx /商:eax
	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
	jnz leap
	jmp noLeap
leap:
	mov eax,offset isLeap
	jmp display
noLeap:
	mov eax,offset notLeap
display:
	call dispmsg
exit 0
end start

5.输入三个无符号整数(可调用readuid子程序),判断并输出这三个数是否能构成一个三角形的三条边。

include io32.inc
.data
	x dword ?
	y dword ?
	z dword ?
	xAddY dword ?
	yAddZ dword ?
	xAddZ dword ?
	isTriangle byte '可以构成三角形',0
	notTriangle byte '不可以构成三角形',0
.code
start:
	;读入三条边
	call readuid
	mov x,eax
	call readuid
	mov y,eax
	call readuid
	mov z,eax

	;任意两边之和
	mov ebx,x
	add ebx,y
	mov xAddY,ebx ;x+y
	mov ebx,y
	add ebx,z
	mov yAddZ,ebx ;y+z
	mov ebx,x
	add ebx,z
	mov xAddZ,ebx ;x+z

	mov ebx,xAddY
	sub ebx,z     ;x+y-z
	jle dispNot
	mov ebx,yAddZ
	sub ebx,x     ;y+z-x
	jle dispNot
	mov ebx,xAddZ
	sub ebx,y     ;x+z-y
	jle dispNot
	jmp dispIs
dispNot:
	mov eax,offset notTriangle
	jmp display
dispIs:
	mov eax,offset isTriangle
	jmp display
display:
	call dispmsg
exit 0
end start

思考题:若这三个数能构成一个三角形的三条边,输出三角形的形状:等腰三角形、等边三角形。(这个程序我发现有错,但我目前没时间改)

include io32.inc
.data
	x dword ?
	y dword ?
	z dword ?
	xAddY dword ?
	yAddZ dword ?
	xAddZ dword ?
	xSubY dword ?
	ySubZ dword ?
	xSubZ dword ?
	isTriangle byte '可以构成三角形',0
	notTriangle byte '不可以构成三角形',0
	dengyaoTri byte '等腰三角形',0
	dengbianTri byte '等边三角形',0
.code
start:
	call readuid
	mov x,eax
	call readuid
	mov y,eax
	call readuid
	mov z,eax

	mov ebx,x
	add ebx,y
	mov xAddY,ebx ;x+y
	mov ebx,y
	add ebx,z
	mov yAddZ,ebx ;y+z
	mov ebx,x
	add ebx,z
	mov xAddZ,ebx ;x+z

	mov ebx,x
	sub ebx,y
	mov xSubY,ebx ;x-y
	mov ebx,y
	sub ebx,z
	mov ySubZ,ebx ;y-z
	mov ebx,x
	sub ebx,z
	mov xSubZ,ebx ;x-z

	mov ebx,xAddY
	sub ebx,z     ;x+y-z
	jle dispNot
	mov ebx,yAddZ
	sub ebx,x     ;y+z-x
	jle dispNot
	mov ebx,xAddZ
	sub ebx,y     ;x+z-y
	jle dispNot

	jmp dispIs
	 
	dispIs:
		mov eax,xSubY
		mov ebx,ySubZ
		or eax,ebx  ;判断等边
		jz dispDB
		jmp isDY
		isDY:    ;判断等腰
			mov eax,xSubY
			mov ebx,ySubZ
			and eax,ebx
			jz dispDY
			mov eax,xSubY
			mov ebx,xSubZ
			and eax,ebx
			jz dispDY
			mov eax,xSubZ
			mov ebx,ySubZ
			and eax,ebx
			jz dispDY
		dispDY:
			mov eax,offset dengyaoTri
			jmp display
		dispDB:
			mov eax,offset dengbianTri
			jmp display
	dispNot:
		mov eax,offset notTriangle
		jmp display

	display:call dispmsg
exit 0
end start

6.采用无条件和条件转移指令构造while和do while循环结构,完成下面的求和任务并输出sum(sum 为双字)。
 sum=1+2+3+….+100

while:

include io32.inc
.data
	n dword 1
	sum dword 0
.code
start:
	mov eax,n
	sub eax,100
	jnle display
	mov eax,sum
	add eax,n
	mov sum,eax
	inc n
	jmp start
display:
	mov eax,sum
	call dispuid
exit 0
end start

do-while:

include io32.inc
.data
	n dword 1
	sum dword 0
.code
start:
	mov eax,sum
	add eax,n
	mov sum,eax
	inc n
	mov eax,n
	sub eax,100
	jnle display
	jmp start
display:
	mov eax,sum
	call dispuid
exit 0
end start

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

include io32.inc
.data
	num dword ?
	promsg byte 'Input Number:0~9',13,10,0
	errmsg byte 'Error!',13,10,0
.code
start:
	mov eax,offset promsg
	call dispmsg
	call readsid
	mov num,eax
	cmp num,0
	jnl next
	jmp error
next:
	cmp num,9
	jle over
error:
	mov eax,offset errmsg
	call dispmsg
	jmp start
over:
exit 0
end start	

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

include io32.inc
include vcio.inc
.data
	array dword 1,4,-2,3,-1,5,7,-3,-2,2
	oddSum dword 0;奇数和
	evenSum dword 0;偶数和
.code
start:
	mov ecx,lengthof array
	mov eax,0;偶数
	mov edx,0;奇数
	mov esi,0
	again:
		mov ebx,array[esi*4]
		test ebx,1
		jnz odd
		add eax,ebx
		jmp next
	odd:
		add edx,ebx
	next:
		inc esi
	loop again
	mov evenSum,eax
	call dispsid
	call dispcrlf
	mov oddSum,edx
	mov eax,oddSum
	call dispsid
exit 0
end start

思考题:(1)最大值与最小值

include io32.inc
include vcio.inc
.data
	array dword 1,4,-2,3,-1,5,7,-3,-2,2
	max dword 0 ;最大值
	min dword 0 ;最小值
.code
start:
	mov ecx,lengthof array
	mov esi,0
	mov eax,array[esi*4] ;设a[0]为最大值初始值
	mov edx,array[esi*4] ;设a[0]为最小值初始值
	again:
		inc esi
		cmp eax,array[esi*4]
		jl changeMax     ;a[n]<a[n+1]
		jmp Min
	changeMax:
		mov eax,array[esi*4] ;更新最大值
	Min:
		cmp edx,array[esi*4]
		jnl changeMin	 ;a[n]>=a[n+1]
		jmp next
	changeMin:
		mov edx,array[esi*4] ;更新最小值
	next:
		loop again
	mov max,eax
	call dispsid
	call dispcrlf
	mov min,edx
	mov eax,min
	call dispsid
exit 0
end start

(2)正数和与负数和

include io32.inc
include vcio.inc
.data
	array dword 1,4,-2,3,-1,5,7,-3,-2,2
	posiSum dword 0 ;正数和
	negaSum dword 0 ;负数和
.code
start:
	mov ecx,lengthof array
	mov esi,0
	mov eax,0 ;正数和初始值=0
	mov edx,0 ;负数和初始值=0
	again:
		mov ebx,array[esi*4]
		cmp ebx,0
		jz next ;判断是否=0
		jl negative
		jmp positive
	negative:
		add edx,ebx
		jmp next
	positive:
		add eax,ebx
	next:
		inc esi
		loop again
	mov posiSum,eax
	call dispsid
	call dispcrlf
	mov negaSum,edx
	mov eax,negaSum
	call dispsid
exit 0
end start

(3)对无符号数求素数和

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

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

include io32.inc
include vcio.inc
.data
	array dword 0,-1,2,-3,4,-5,6,-7,8,-9
.code
start:
	mov ecx,lengthof array
	sub ecx,1
	mov esi,0  ;数组下标
	.while esi<ecx
		mov eax,array[esi*4]
		mov ebx,array[ecx*4]
		mov edx,eax
		mov eax,ebx
		mov ebx,edx
		mov array[esi*4],eax
		mov array[ecx*4],ebx
		inc esi
		dec ecx
	.endw
	mov ecx,lengthof array
	mov esi,0
display:
	mov eax,array[esi*4]
	call dispsid
	call dispcrlf
	inc esi
	loop display
exit 0
end start

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

include io32.inc
include vcio.inc
.data
	space byte ' ',0
	f1 dword 1
	f2 dword 1
.code
start:
	mov ecx,30
	mov eax,f1
	call disp
	dec ecx
	mov eax,f2
	call disp
	dec ecx
again:
	mov eax,f1
	add eax,f2
	call disp
	mov ebx,f2
	mov f1,ebx
	mov f2,eax
	loop again
	jmp done
disp proc 
	push eax
	call dispuid
	mov eax,offset space
	call dispmsg
	pop eax
	ret
disp endp
done:
	exit 0
	end start

11.编程写一个完整的程序,显示2012年~2099年中的所有闰年年份,并存入Lyear数组中。
在这里插入图片描述

include io32.inc
.data
	Lyear dword ?
.code
start:
	mov esi,0
	mov ecx,2012
	.while ecx<2100
		xor edx,edx
		mov eax,ecx
		mov ebx,400
		div ebx
		cmp edx,0
		jz leap  ;是闰年
		mov eax,ecx
		xor edx,edx
		mov ebx,4
		div ebx
		cmp edx,0
		jnz next ;不是闰年
		mov eax,ecx
		xor edx,edx
		mov ebx,100
		div ebx
		cmp edx,0
		jnz leap ;是闰年
	leap:
		mov eax,ecx
		call dispuid
		call dispcrlf
		mov Lyear[esi*4],ecx
		inc esi
	next:
		inc ecx
	.endw
exit 0
end start

12.有一个首地址为string的字符串 ,分别统计string中空格、英文小写字母的个数并输出,还可统计数字和其它字符的个数。

include io32.inc
.data
string byte 'Let Me Try!',0
countofspace dword ?
countofletter dword ?
countofdigit dword ?
countofother dword ?
.code
start:
	xor edx,edx
again:
	mov al,string[edx]
	cmp al,0
	jz done
	cmp al,' '
	jz space
	cmp al,'a'
	jge letter_lower
	continue_upper:
		cmp al,'A'
		jge letter_upper
	continue_digit:
		cmp al,'0'
		jge digit0
	continue_other:
		inc countofother
	continue:
		inc edx
		jmp again
	space:
		inc countofspace
		jmp continue
	letter_lower:
		cmp al,'z'
		jle lower
		jmp continue_upper
	lower:
		inc countofletter
		jmp continue
	letter_upper:
		cmp al,'Z'
		jle upper
		jmp continue_digit
	upper:
		inc countofletter
		jmp continue
	digit0:
		cmp al,'9'
		jle digit9
		jmp continue_other
	digit9:
		inc countofdigit
		jmp continue
	done:
		mov eax,countofspace
		call dispuid
		call dispcrlf
		mov eax,countofletter
		call dispuid
		call dispcrlf
		mov eax,countofdigit
		call dispuid
		call dispcrlf
		mov eax,countofother
		call dispuid
		call dispcrlf
exit 0
end start

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

include io32.inc
include vcio.inc
.data
msg byte 13,10,0
fmts byte '%s',0
fmtd byte '%d',0
tabb byte ' '
.code
main proc
mov ecx,10
mov ebx,ecx;10做除数
.while(ecx<=10000)
  xor esi,esi
  mov eax,ecx;eax存放被除数
  .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
    invoke printf,offset tabb
  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

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

include io32.inc
.data
string byte 'Let me try',0
.code
main proc
  mov eax,offset string
  call dispmsg
  call dispcrlf
  mov ecx,lengthof string
  dec ecx
  again:
    mov al,string[ecx]
    cmp al,' '
    jz delt
    dec ecx
    jl done
    jmp again
  
  delt:
    mov ebx,ecx

  afterdelt:
    mov al,string[ebx+1]
    mov string[ebx],al
    test al,al
    jz again
    inc ebx
    jmp afterdelt
  done:
    mov eax,offset string
    call dispmsg
    call dispcrlf

main endp
end main

15.编写一个求n!的子程序,利用它求1!+2! +3! +4! +5! +6! +7! +8! 的和(=46233 )并输出。要求参数的传递分别采用:寄存器传递、全局变量传递、堆栈传递三种不同的方法实现。

寄存器传递:

include io32.inc
include vcio.inc
.data
	sum dword 0
.code
main proc
	mov ebx,1
	.while ebx<=8
		call fac
		add sum,eax
		inc ebx
	.endw
	mov eax,sum
	call dispuid
	call dispcrlf
	ret
main endp
fac proc
	mov ecx,1
	mov eax,1
	.while ecx<=ebx
		imul eax,ecx
		inc ecx
	.endw
	ret
fac endp
end main

全局变量传递:

include io32.inc
include vcio.inc
.data
	sum dword 0
	temp dword ?
.code
main proc
	mov temp,1
	.while temp<=8
		call fac
		add sum,eax
		inc temp
	.endw
	mov eax,sum
	call dispuid
	call dispcrlf
	ret
main endp
fac proc
	mov ecx,1
	mov eax,1
	.while ecx<=temp
		imul eax,ecx
		inc ecx
	.endw
	ret
fac endp
end main

堆栈传递:

include io32.inc
include vcio.inc
.data
	sum dword 0
.code
main proc
	mov ebx,1
	.while ebx<=8
		push ebx
		call fac
		add sum,eax
		inc ebx
	.endw
	mov eax,sum
	call dispuid
	call dispcrlf
	ret
main endp
fac proc
	push ebp
	mov ebp,esp

	mov ecx,1
	mov eax,1
	.while ecx<=[ebp+8]
		imul eax,ecx
		inc ecx
	.endw
	pop ebp
	ret 1*4
fac endp
end main

16.编写一个判断闰年的子程序,利用它求出2010年到2060年之间所有的闰年并输出。建议采用堆栈传递参数。

include io32.inc
include vcio.inc
.data
	fmt byte '%d ',0
	flag dword ?
.code
	main proc
		mov ecx,2010
		.while ecx<=2060 ;ecx
			push ecx
			call leap
			.if flag==1
				pushad
					invoke printf,offset fmt,ecx
				popad
			.endif
			inc ecx
		.endw
		ret
	main endp

leap proc
	push ebp
	mov ebp,esp

	mov eax,[ebp+8]
	mov edx,0
	mov ebx,400
	div ebx
	cmp edx,0
	je yes

	mov eax,[ebp+8]
	mov edx,0
	mov ebx,4
	div ebx
	cmp edx,0
	jne no

	mov eax,[ebp+8]
	mov edx,0
	mov ebx,100
	div ebx
	cmp edx,0
	je no
yes:
	mov flag,1
	jmp done
no:
	mov flag,0
done:
	pop ebp
	ret 1*4
leap endp

end main

17.编程写一个名为Prime的子程序,用于测试一个整数是否是素数,主子程序间的参数传递通过堆栈完成。调用Prime子程序求出2~100之间的所有素数,并将它们存入Parray数组中,素数的个数存入变量Pcounter中。

include io32.inc
include vcio.inc
.data
	fmt byte '%d ',0
	flag dword ?
.code
	main proc
		mov ecx,2
		.while ecx<=100 ;ecx
			push ecx
			call prime
			.if flag==1
				pushad
					invoke printf,offset fmt,ecx
				popad
			.endif
			inc ecx
		.endw
		invoke _getch
		ret
	main endp

prime proc
	push ebp
	mov ebp,esp
	mov ebx,[ebp+8]
	mov esi,2
	.while esi<ebx
		mov edx,0
		mov eax,ebx
		div esi
		cmp edx,0
		je no
		inc esi
	.endw
	mov flag,1
	jmp done
no:
	mov flag,0
done:
	pop ebp
	ret 1*4
prime endp

end main

18.编程写一个名为Gcd的求两个数最大公约数子程序,主子程序间的参数传递通过堆栈完成。调用Gcd子程序求出三个双字变量:dvar1、dvar2与dvar3的最大公约数并输出。

include io32.inc
include vcio.inc
.data
	dvar1 dword 2012
	dvar2 dword 128
	dvar3 dword 456
	dgcd dword ?
	fmtStr byte 'gcd(%d,%d,%d)=%d',13,10,0
.code
main proc 
	push dvar1
	push dvar2
	push offset dgcd
	call Gcd
		push dvar3
		push dgcd
		push offset dgcd
		call Gcd
	invoke printf,offset fmtStr,dvar1,dvar2,dvar3,dgcd
	ret
main endp
Gcd proc
	push ebp
	mov ebp,esp
	push eax
	push ebx
	push ecx
	push edx
	mov ebx,[ebp+8]
	mov ecx,[ebp+12]
	mov eax,[ebp+16]
	.while
		xor edx,edx
		div ecx
		mov eax,ecx
		mov ecx,edx
	.endw
	mov [ebx],eax
	restore:
		pop edx
		pop ecx
		pop ebx
		pop eax
		pop ebp
		ret 3*4
Gcd endp
end main

19.编写一子程序,将一个32位二进制数用8位十六进制形式在屏幕上显示出来。采用堆栈方法传递这个32位二进制数,并写主程序验证它。显示一个字符的子程序为:dispc,入口参数:AL=要显示个字符的SACII码。

include io32.inc
.data
	wvar dword 307281AFH
.code
	start:
		push wvar
		call disp
		add esp,4
		mov al,'H'
		call dispc
	disp proc
		push ebp
		mov ebp,esp
		push ebx
		push ecx
		mov ecx,8
		mov eax,[ebp+8]
	dhw1:
		rol eax,4
		mov ebx,eax
		and al,0fh
		add al,30h
		cmp al,'9'
		jbe dhw2
		add al,7
	dhw2:
		call dispc
		mov eax,ebx
		loop dhw1
		pop ecx
		pop ebx
		pop ebp
		ret
	disp endp
	exit 0
	end start

20.编程写一个名为Bubble的冒泡排序子程序,主子程序间的参数传递通过堆栈完成;并写主程序验证它。

include vcIO.inc
.data
	print dword 0 
	n dword 6
	x1 dword ?
	x2 dword ?
	x3 dword ?
	x4 dword ?
	x5 dword ?
	x6 dword ?
	input_str byte '%d',0
	output_str byte '%d',0ah,0
.code

bubble proc 
	mov ecx,n 
	dec ecx
	.while ecx>0 
		mov esi,esp 
		add esi,4 
		mov ebx,ecx
		.while ebx>0
			mov eax,[esi]
			.if eax > [esi+4]
				xchg eax,[esi+4]
				mov [esi],eax
			.endif
			add esi,4 
			dec ebx
		.endw
		dec ecx
	.endw
	ret
bubble endp

main proc
		invoke scanf,offset input_str,offset x1
		push x1
		invoke scanf,offset input_str,offset x2
		push x2
		invoke scanf,offset input_str,offset x3
		push x3
		invoke scanf,offset input_str,offset x4
		push x4
		invoke scanf,offset input_str,offset x5
		push x5
		invoke scanf,offset input_str,offset x6
		push x6
	call bubble
	mov ecx,n 
	s:
		pop print
		pushad
			invoke printf,offset output_str,print
		popad
	loop s
	ret
main endp
end main
  • 13
    点赞
  • 113
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值