汇编语言实验+题目

汇编语言实验

本学期汇编课程已经结束,整理一下曾经做过的题目和写过的汇编代码。

使用dosbox环境masm5.0编译器,debug方式可以看我这篇文章https://blog.csdn.net/qq_41420747/article/details/89419241

 

  • 实验题

循环程序设计

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*偏移地址


7. 溢出标志可以用来判断运算的结果是否产生溢出。(X)

溢出标志指CF标志位,但是有些运算不是靠CF标志溢出

 

8. 对于有符号的数来说,下列哪个值最大(D )

A、0F8H
B、11010011B
C、82
D、123Q

AB是负数,对于A第一个0是因为汇编中的16进制不允许用字母开头,故A其实就是F8H。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值