汇编语言实验
本学期汇编课程已经结束,整理一下曾经做过的题目和写过的汇编代码。
使用dosbox环境masm5.0编译器,debug方式可以看我这篇文章https://blog.csdn.net/_/article/details/
-
实验题
循环程序设计
1. 有一个首地址为Arr的N字数组,编程求数组中的最大值和最小值,并存入MAX和MIN地址单元中。
Data segment Arr dw 1H,3H,2H N EQU 3 ; 这里可以 $-Arr / 2 因为dw 是双字节 Max dw ? Min dw ? Data ends Code segment Assume cs:Code, ds:Data Start: mov ax,Data mov ds,ax mov dx,Arr mov ax,Arr mov si,00H mov cx,N-1 NEXT: add si,2 cmp dx,Arr[si] jle jmp1 mov dx,Arr[si] jmp1: ; do nothing cmp ax,Arr[si] jge jmp2 mov ax,Arr[si] jmp2: ; do nothing LOOP NEXT mov Max,dx mov Min,ax MOV AH,4CH ;返回dos INT 21H Code ends end Start
讯享网
调试结果:
2. 显示一个十六进制数(XXXXH)
思路:循环位移4位后,每次取出bx(存放16进制数)的低第四位,加上‘0’判断是否在0-9ascii码范围内在则直接打印不在则加7再打印,重复4次。最后打印一个’H’。测试数:1E2AH存入BX
讯享网Code segment assume cs:Code start: mov ax,Code mov ds,ax xor ax,ax; to 0 xor cx,cx; to 0 xor bx,bx; to 0 mov bx,1E2AH mov ch,4 rotate: mov cl,4 rol bx,cl mov al,bl and al,0FH add al,30H cmp al,3aH jl print add al,7H print: mov dl,al mov ah,2 int 21H dec ch jnz rotate mov dl,'H' mov ah,2 int 21H mov ah,4cH int 21H Code ends end start
运行结果:

3. 编制一个程序把BX寄存器内的二进制数用十进制的形式在屏幕上显示出来。
思路: 将bx中的内容mov到ax,分别除10000,1000,100,10,将商放到data segment存起来,将余数放回ax继续除,直到余数为一位数,再将data segment的数顺序打印出来。
Datas segment decnum db 5 dup(?) Datas ends Code segment assume cs:Code,ds:Datas start: mov ax,Datas mov ds,ax mov bx,0FFFFH ; 要转换的数 lea si,decnum mov dx,0 ;dx一定要置零 mov ax,bx mov cx,10000 div cx mov [si],al inc si mov ax,dx;把上一次运算的余数放入ax mov dx,0 mov cx,1000 div cx mov [si],al inc si mov ax,dx mov dx,0 mov cx,100 div cx mov [si],al inc si mov ax,dx mov dx,0 mov cx,10 div cx mov [si],al inc si mov [si],dl ;循环打印data段数据 decnum lea si,decnum mov cx,5 next: mov dx,[si] add dx,'0' mov ah,2 int 21H inc si loop next mov ah,4cH int 21H Code ends end start
运行结果:

调试

分支程序设计
1. 设有10个学生的成绩分别是76,69,84,90,73,88,99,63,100和80分。试编制一个程序统计60~69分,70~79分,80~89分,90~99分和100分的人数,分别存放到S6,S7,S8,S9和S10单元中。
讯享网Datas segment STU db 76,69,84,90,73,88,99,63,100,80 S6 db 0 S7 db 0 S8 db 0 S9 db 0 S10 db 0 Datas ends Code segment assume ds:Datas,cs:Code start: mov ax,Datas mov ds,ax xor ax,ax mov si,0 mov cx,10 next: mov al,byte ptr [si] cmp ax,69 jg jmp1 add S6,1 jmp final jmp1: cmp ax,79 jg jmp2 add S7,1 jmp final jmp2: cmp ax,89 jg jmp3 add S8,1 jmp final jmp3: cmp ax,99 jg jmp4 add S9,1 jmp final jmp4: add S10,1 final: inc si loop next mov dl,S6 mov ah,2H int 21H mov dl,S7 mov ah,2H int 21H mov dl,S8 mov ah,2H int 21H mov dl,S9 mov ah,2H int 21H mov dl,S10 mov ah,2H int 21H mov ah,4cH int 21H Code ends end start
运行结果:

2. 试编写一个汇编语言程序,要求对键盘输入的小写字母用大写字母显示出来。
Data segment max_len db 100 real_len db ? str1 db 100 dup('$') Data ends Code segment assume cs:code,ds:data start: mov ax,data mov ds,ax lea dx,max_len mov ah,0AH int 21H mov dl,0DH mov ah,02H int 21H mov dl,0AH mov ah,02H int 21H ; 字符大小写转换 xor cx,cx mov cl,real_len mov si,0 lop: mov bl,str1[si] cmp bl,61H jb ok cmp bl,7AH ja ok sub bl,20H mov str1[si],bl ok: inc si loop lop lea dx,str1 mov ah,09H int 21H mov ah,4cH int 21H Code ends end start
运行结果:

3. 以T为首地址定义10个带符号数(补码),将负数去掉,正数按原序排列,并显示正数。
思路:如果一个长度为一个字节的十六进制数高位为大于9的数,那这个数就是负数,所以遍历整个数组,判断每个十六进制数的高位大小,跳过负数,输出正数。
讯享网Data segment num db 0AAH,01H,02H,0ABH,03H,04H,05H,06H,07H,0FFH count db 10 Data ends Code segment assume cs:Code,ds:Data start: mov ax,Data mov ds,ax xor bl,bl xor cx,cx ; to 0 mov cl,count mov si,0 ; 筛选正数并输出 next: mov bl,num[si] rcl bl,1 jc lop ; output ; 十位 mov bl,num[si] shr bl,1 shr bl,1 shr bl,1 shr bl,1 and bl,0FH mov dl,bl cmp dl,09H ja big1 add dl,30H jmp outt1 big1: add dl,36H outt1: mov ah,02H int 21H ; 个位 mov bl,num[si] and bl,0FH mov dl,bl cmp dl,09H ja big2 add dl,30H jmp outt2 big2: add dl,36H outt2: mov ah,02H int 21H ; 输出H mov dl,'H' mov ah,02H int 21H lop: inc si loop next mov ah,4cH int 21H Code ends end start
运行结果:

4. 试编写一个汇编语言程序,要求从键盘接收一个四位的十六进制数,并在终端显示与它等值的二进制数。
code segment assume cs:code start: mov bx,0 mov ch,4 mov cl,4 s0: mov ah,1 ;输入4个16进制数 int 21h cmp al,39h ;判断 0~9 or A~H jbe next sub al,07h next: sub al,30h shl bx,cl add bl,al dec ch jnz s0 mov cx,16 ;显示 mov dl,0AH ;换行 mov ah,02H int 21H s1: mov dl,0 rol bx,1 ;最高位入CF adc dl,30h mov ah,02h int 21h loop s1 mov ax,4c00h int 21h code ends end start
运行结果:

5. 试编写一个程序,要求比较数组ARRAY中的三个16位补码数,并根据比较结果在终端上显示如下信息
(1)如果三个数都不相等则显示0;
(2)如果三个数有两个数相等则显示1;
(3)如果三个数都相等,则显示2.
讯享网Data segment ARRAY DW 1,2,3 Data ends Code segment assume cs:Code,ds:Data Main PROC FAR start: MOV AX,DATA MOV DS,AX MOV AX,word ptr ARRAY MOV BX,word ptr ARRAY[2] CMP AX,word ptr ARRAY[2]; AB比较 je AB_E CMP AX,word ptr ARRAY[4]; AC比较 je AC_E CMP BX,word ptr ARRAY[4]; BC比较 je BC_E MOV dl,30H JMP EXIT AB_E: CMP BX,word ptr ARRAY[4]; BC比较 je BC_E2 MOV dl,31H JMP EXIT AC_E: MOV dl,31H JMP EXIT BC_E: MOV dl,31H JMP EXIT BC_E2: MOV dl,32H JMP EXIT EXIT: MOV AH,2 INT 21H MOV AH,4CH INT 21H Code ends Main endp end start
运行结果:

子程序设计
1. 求1+2+3+……n的和,并以十进制数形式显示此数。

data segment decnum db 5 dup(?) data ends code segment assume cs:code,ds:data main proc far start: mov ax,data mov ds,ax mov cx,20 ;从1加到xxx call sumfunc ;使用cx寄存器传参,bx存返回值 call printfunc mov ah,4ch int 21h main endp sumfunc proc near xor bx,bx xor ax,ax lop: add ax,1 add bx,ax loop lop ret sumfunc endp printfunc proc near LEA SI,DECNUM ;偏移地址传送 MOV DX,0 MOV AX,BX MOV CX,10000 DIV CX MOV [SI],AL ;求得万位的值,存入指定单元 INC SI MOV AX,DX ;上次计算的余数存在DX中 MOV DX,0 MOV CX,1000 DIV CX MOV [SI],AL ;求得千位的值,存入指定单元 INC SI MOV AX,DX MOV DX,0 MOV CX,100 DIV CX MOV [SI],AL ;求得百位的值,存入指定单元 INC SI MOV AX,DX MOV CL,10 DIV CL MOV [SI],AL ;求得十位的值,存入指定单元 INC SI MOV [SI],AH ;存个位的值 LEA SI,DECNUM ;开始显示存储单元中的十进制数 MOV CX,5 DISP: MOV DL,[SI] ;依次取出十进制数各位的值 OR DL,30H ;将取出的值转换为ASCII值 MOV AH,2 INT 21H ;利用DOS功能调用,显示 INC SI LOOP DISP MOV DL,'D' MOV AH,2 INT 21H ret printfunc endp code ends end start
运行结果:

2. 从键盘输入一个十进制数然后以十六进制输出
讯享网DATA SEGMENT NUM10 DB 5;定义缓冲区长度 DB ?;实际输入字符个数的计数单元 DB 5 DUP(0) NUM16 DB 4 DUP(?) ENDSING DB '$' DATA ENDS CODE SEGMENT ASSUME DS:DATA,CS:CODE MAIN PROC FAR START: MOV AX,DATA MOV DS,AX CALL INPUT CALL TURN CALL PRINT16 MOV AH,4CH ;返回dos INT 21H MAIN ENDP TURN PROC NEAR XOR BX,BX XOR AX,AX XOR CX,CX MOV CL,BYTE PTR [NUM10+1] MOV SI,2 MOV DI,0AH LOP1: MUL DI MOV BL,BYTE PTR NUM10[SI] SUB BL,30H ADD AX,BX INC SI LOOP LOP1 ;到这里ax存了输入的数 ;接下来转换16进制存入num16地址单元 MOV CL,04H MOV CH,04H MOV SI,0 LOP2: XOR BX,BX ;清空bx ;位移ax ROL AX,CL MOV BL,AL AND BL,0FH CMP BL,09H JA ZIMU CONTI: ADD BL,30H MOV NUM16[SI],BL ;储存 INC SI DEC CH JNZ LOP2 RET ;循环结束推出子程序 ZIMU: ;转字母 ADD BL,07H JMP CONTI TURN ENDP INPUT PROC NEAR LEA DX,NUM10 MOV AH,0AH INT 21H RET INPUT ENDP PRINT16 PROC NEAR MOV AH,02H MOV DL,0DH ;回车 INT 21H MOV AH,02H MOV DL,0AH ;换行 INT 21H LEA DX,NUM16 MOV AH,09H INT 21H MOV AH,02H MOV DL,'H' ;'H' INT 21H RET PRINT16 ENDP CODE ENDS END START
运行结果:

-
练习题目
这里我就不分章节了,只记录一些比较难懂的题目。
1. 在汇编语言程序中,对END语句的叙述正确的是( C )。
A、END语句是一可执行语句
B、END语句表示程序执行到此结束
C、END语句表示源程序到此结束
D、END语句在汇编后要产生机器码
2. 假设OP1,OP2是已经用DB定义的变量,判断指令格式是否正确
CMP 15, BX (x)
CMP OP1, OP2(x)
CMP AX, OP1(x)
CMP OP1, 25(√)
3. 假设VAR1和VAR2为字变量,LAB为标号
JMP LAB [SI](x)
JNZ VAR1(x)
4. 语句LENGTH=SIZE*TYPE是合法的。(x)
5. 指出下列指令的错误原因,假设下列指令中的所有标识符均为类型属性为字的变量
(1) MOV AH, BX
数据类型不一致
(2) MOV AX, [SI][DI]
只有变址+基址寻址方式,没有变址+变址寻址方式
(3) MOV BYTE PTR [BX], 1000
立即数和指定的操作数类型不一致,指定为字节操作,1000为字类型
(4) MOV CS, AX
CS代码段寄存器,该寄存器只能由系统管理
(5) MOV WORD_OP1, WORD_OP2
不允许两个内存单元直接传递数据
(6) MOV AX, WORD_OP1+WORD_OP2
两个内存单元地址相加没有意义
(7) SUB [BX],2
未指定数据类型
6. 8086/8088系统中,存储器是分段组织的,存储器物理地址计算式是( B )
A、段地址+偏移地址
B、段地址*10H+偏移地址
C、段地址*16H+偏移地址
D、段地址+10H*偏移地址
溢出标志指CF标志位,但是有些运算不是靠CF标志溢出
8. 对于有符号的数来说,下列哪个值最大(D )
A、0F8H
B、B
C、82
D、123Q
AB是负数,对于A第一个0是因为汇编中的16进制不允许用字母开头,故A其实就是F8H。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/63921.html