题目总览
常用指令
指令 | 含义 |
---|---|
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