本文共 7586 字,大约阅读时间需要 25 分钟。
本学期汇编课程已经结束,整理一下曾经做过的题目和写过的汇编代码。
使用dosbox环境masm5.0编译器,debug方式可以看我这篇文章
1. 有一个首地址为Arr的N字数组,编程求数组中的最大值和最小值,并存入MAX和MIN地址单元中。
Data segment Arr dw 1H,3H,2H N EQU 3 ; 这里可以 $-Arr / 2 因为dw 是双字节 Max dw ? Min dw ?Data endsCode segment Assume cs:Code, ds:DataStart: mov ax,Data mov ds,ax mov dx,Arr mov ax,Arr mov si,00H mov cx,N-1NEXT: 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 21HCode ends end Start
调试结果:
2. 显示一个十六进制数(XXXXH)
思路:循环位移4位后,每次取出bx(存放16进制数)的低第四位,加上‘0’判断是否在0-9ascii码范围内在则直接打印不在则加7再打印,重复4次。最后打印一个’H’。测试数:1E2AH存入BX
Code segment assume cs:Codestart: 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,4rotate: 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 21HCode ends end start
运行结果:
3. 编制一个程序把BX寄存器内的二进制数用十进制的形式在屏幕上显示出来。
思路: 将bx中的内容mov到ax,分别除10000,1000,100,10,将商放到data segment存起来,将余数放回ax继续除,直到余数为一位数,再将data segment的数顺序打印出来。
Datas segment decnum db 5 dup(?)Datas endsCode segment assume cs:Code,ds:Datasstart: 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,5next: mov dx,[si] add dx,'0' mov ah,2 int 21H inc si loop next mov ah,4cH int 21HCode 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 0Datas ends Code segment assume ds:Datas,cs:Codestart: 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 finaljmp1: cmp ax,79 jg jmp2 add S7,1 jmp finaljmp2: cmp ax,89 jg jmp3 add S8,1 jmp finaljmp3: cmp ax,99 jg jmp4 add S9,1 jmp finaljmp4: 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 endsCode segment assume cs:code,ds:datastart: 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],blok: inc si loop lop lea dx,str1 mov ah,09H int 21H mov ah,4cH int 21HCode endsend start
运行结果:
3. 以T为首地址定义10个带符号数(补码),将负数去掉,正数按原序排列,并显示正数。
思路:如果一个长度为一个字节的十六进制数高位为大于9的数,那这个数就是负数,所以遍历整个数组,判断每个十六进制数的高位大小,跳过负数,输出正数。
Data segment num db 0AAH,01H,02H,0ABH,03H,04H,05H,06H,07H,0FFH count db 10Data endsCode segment assume cs:Code,ds:Datastart: 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 outt1big1: add dl,36Houtt1: mov ah,02H int 21H ; 个位 mov bl,num[si] and bl,0FH mov dl,bl cmp dl,09H ja big2 add dl,30H jmp outt2big2: add dl,36Houtt2: mov ah,02H int 21H ; 输出H mov dl,'H' mov ah,02H int 21H lop: inc si loop next mov ah,4cH int 21HCode ends end start
运行结果:
4. 试编写一个汇编语言程序,要求从键盘接收一个四位的十六进制数,并在终端显示与它等值的二进制数。
code segment assume cs:codestart: mov bx,0mov ch,4mov cl,4s0: mov ah,1 ;输入4个16进制数int 21hcmp al,39h ;判断 0~9 or A~Hjbe nextsub al,07hnext: sub al,30hshl bx,cladd bl,al dec chjnz s0 mov cx,16 ;显示mov dl,0AH ;换行mov ah,02Hint 21Hs1:mov dl,0rol bx,1 ;最高位入CFadc dl,30hmov ah,02hint 21hloop s1mov ax,4c00hint 21hcode ends end start
运行结果:
5. 试编写一个程序,要求比较数组ARRAY中的三个16位补码数,并根据比较结果在终端上显示如下信息
(1)如果三个数都不相等则显示0;
(2)如果三个数有两个数相等则显示1;
(3)如果三个数都相等,则显示2.
Data segmentARRAY DW 1,2,3Data endsCode segment assume cs:Code,ds:DataMain PROC FARstart:MOV AX,DATAMOV DS,AXMOV AX,word ptr ARRAYMOV BX,word ptr ARRAY[2]CMP AX,word ptr ARRAY[2]; AB比较je AB_ECMP AX,word ptr ARRAY[4]; AC比较je AC_ECMP BX,word ptr ARRAY[4]; BC比较je BC_EMOV dl,30HJMP EXITAB_E:CMP BX,word ptr ARRAY[4]; BC比较je BC_E2MOV dl,31HJMP EXITAC_E:MOV dl,31HJMP EXITBC_E:MOV dl,31HJMP EXITBC_E2:MOV dl,32HJMP EXITEXIT:MOV AH,2INT 21HMOV AH,4CH INT 21HCode ends Main endp end start
运行结果:
1. 求1+2+3+……n的和,并以十进制数形式显示此数。
data segment decnum db 5 dup(?)data endscode segment assume cs:code,ds:data main proc farstart: mov ax,data mov ds,ax mov cx,20 ;从1加到xxx call sumfunc ;使用cx寄存器传参,bx存返回值 call printfunc mov ah,4ch int 21h main endpsumfunc proc near xor bx,bx xor ax,axlop: add ax,1 add bx,ax loop lop retsumfunc endpprintfunc 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,5DISP: 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 retprintfunc endpcode ends end start
运行结果:
2. 从键盘输入一个十进制数然后以十六进制输出
DATA SEGMENT NUM10 DB 5;定义缓冲区长度 DB ?;实际输入字符个数的计数单元 DB 5 DUP(0) NUM16 DB 4 DUP(?) ENDSING DB '$'DATA ENDSCODE 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 ENDPTURN PROC NEAR XOR BX,BX XOR AX,AX XOR CX,CX MOV CL,BYTE PTR [NUM10+1] MOV SI,2 MOV DI,0AHLOP1: 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,0LOP2: XOR BX,BX ;清空bx ;位移ax ROL AX,CL MOV BL,AL AND BL,0FH CMP BL,09H JA ZIMUCONTI: ADD BL,30H MOV NUM16[SI],BL ;储存 INC SI DEC CH JNZ LOP2 RET ;循环结束推出子程序ZIMU: ;转字母 ADD BL,07H JMP CONTI TURN ENDPINPUT PROC NEAR LEA DX,NUM10 MOV AH,0AH INT 21H RETINPUT ENDPPRINT16 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 RETPRINT16 ENDPCODE 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*偏移地址 7. 溢出标志可以用来判断运算的结果是否产生溢出。(X)溢出标志指CF标志位,但是有些运算不是靠CF标志溢出
8. 对于有符号的数来说,下列哪个值最大(D )
A、0F8H
B、11010011B C、82 D、123QAB是负数,对于A第一个0是因为汇编中的16进制不允许用字母开头,故A其实就是F8H。
转载地址:http://znoen.baihongyu.com/