✅
Experiment 时刻!⌨️
上一篇文章链接:【计算机与UNIX汇编原理⑧】——UNIX编程进阶【分支程序、循环程序、子程序、宏指令】.
下一篇文章链接:【计算机与UNIX汇编原理⑩】——汇编语言程序设计举例【三种进制转换】.
一、排除语法错误【实验内容一】
● 题目描述:下面给出的是一个通过比较法完成 8 位二进制数转换成十进制数送屏幕显示功能的汇编语言源程序,但有很多语法错误。要求实验者按照原样对源程序进行编辑,汇编后,根据 MASM 给出的错误信息对源程序进行修改,直到没有语法错误为止。然后进行链接,并执行相应的可执行文件。正确的执行结果是在屏幕上显示 25+9=34 。
● 右边的注释是我后面加的(主要错误):
"右边的注释是我后面加的(主要错误)"
;FILEANAME: EXA131.ASM
.486
DATA SEGME -NT USE16
SUM DB ?, ?,
MESG DB '25+9=' ; 可以和下面句进行整合, 记得加结束符号 “$”
DB 0, 0
N1 DB 9, F0H ; 多了个 FOH
N2 DW 25
DATA ENDS
CODE SEGMENT USE16
ASSUME CS:CODE, DS:DATA
BEG: MOV AX, DATA
MOV DS, AX
MOV BX, OFFSET SUM
MOV AH, N1
MOV AL, N2
ADD AH, AL
MOV [BX], AH ; PTR 的应用(包括后面)
CALL CHANG
MOV AH, 9
MOV DX, OFFSEG MEST
INT 21H
MOV AH, 4CH
INT 21H
CHANG: PROC ; 子程序格式
LAST: CMP [BX], 10
JC NEXT
SUB [BX], 10
INC [BX+7]
JMP LAST
NEXT: ADD [BX+8], SUM ; 没有这种寻址方式
ADD [BX+7], 30H
ADD [BX+8], 30H
RET
CHANG: ENDP
CODE ENDS
END BEG
● 修改后的代码如下图所示:
;FILEANAME: EXA131.ASM
.586 ; 我们一般用 .586
DATA SEGMENT USE16
SUM DB ?, ?
MESG DB '25+9=', 0, 0, '$'
N1 DB 9
N2 DW 25
DATA ENDS
CODE SEGMENT USE16
ASSUME CS:CODE, DS:DATA
BEG: MOV AX, DATA
MOV DS, AX
MOV BX, OFFSET SUM
MOV AH, N1
MOV AL, BYTE PTR N2 ; N2 为字属性, 需要改一下
ADD AH, AL ; 实现加法
MOV [BX], AH ; 规则里没有,所以我们默认是对的
CALL CHANG
MOV AH, 09H ; 显示字符串
MOV DX, OFFSET MESG ; 前面只有名为 “MESG” 的变量
INT 21H
MOV AH, 4CH ; 终止
INT 21H
CHANG PROC ; 不需要 ":"
LAST: CMP BYTE PTR [BX], 10 ; 违反双操作数第(2)条规则, 需要改一下
JC NEXT ; < 10 的话(发生借位), 进行跳转
SUB BYTE PTR [BX], 10 ; 减 10 操作
INC BYTE PTR [BX+7] ; 逢十进一
JMP LAST ; 无条件转移指令
NEXT: ;MOV [BX+8], SUM ; 源操作数和目的操作数不能同时为存储器
MOV AH, [BX] ; [BX] 也可以换成 SUM
MOV [BX+8], AH
ADD BYTE PTR [BX+7], 30H ; 十位转换为 ASCII
ADD BYTE PTR [BX+8], 30H ; 个位转换为 ASCII
RET
CHANG ENDP ; 不需要 ":"
CODE ENDS
END BEG
● 思考与小结一:该实验主要训练我们的 “调试” 能力(如下图所示),还有对于基础知识点的理解。这里有一个关键点,SUM 变量和 BX 其实是同一个东西,当 BX 发生变化时,SUM 也会发生变化。
● 思考与小结二:一般 DS:DX 指向放键入字符的缓冲区,但字符串的储存形式和一般的不太一样。所以
[
B
X
+
2
]
[BX+2]
[BX+2] 其实才是 “25+9=” 中的 “2”。
● 思考与小结三:MOV AX,BX 是把寄存器 BX 中的内容给 AX。而 MOV AX,[BX] 是先把 BX 中的内容取出来,作为偏移地址,算出物理地址,再把这个地址的内容送给 AX。(比如说 BX 中的内容是 1021,就是去把地址为 1100 内存单元的数据送给 AX)。另外,[BX+7] 是基址寻址,参考文章: 【计算机和UNIX汇编原理④】——指令系统(上)【标志寄存器 立即寻址 寄存器寻址 直接/寄存器/基址/变址寻址 万字总结】.
● 修改的第二种方法:先输出 “25+9”,然后依次输出 “3” 和 “4”(单字符)。
;FILEANAME: EXA131.ASM
.586 ; 我们一般用 .586
DATA SEGMENT USE16
SUM DB ?, ?
MESG DB '25+9=', '$'
N1 DB 9
N2 DW 25
DATA ENDS
CODE SEGMENT USE16
ASSUME CS:CODE, DS:DATA
BEG: MOV AX, DATA
MOV DS, AX
MOV AH, N1
MOV AL, BYTE PTR N2 ; N2 为字属性, 需要改一下
ADD AH, AL ; 实现加法
MOV SUM, AH
MOV AH, 09H ; 显示字符串
MOV DX, OFFSET MESG
INT 21H
CALL CHANG
MOV AH, 4CH ; 终止
INT 21H
CHANG PROC
LAST: CMP BYTE PTR SUM, 10
JC NEXT ; < 10 的话(发生借位), 进行跳转
SUB BYTE PTR SUM, 10
INC BYTE PTR BH ; 逢十进一
JMP LAST ; 无条件转移指令
NEXT:
ADD BYTE PTR BH, 30H
MOV AH, 02H ; 显示单字符
MOV DL, BH
INT 21H
ADD BYTE PTR SUM, 30H ; 个位转换为 ASCII
MOV AH, 02H
MOV DL, SUM
INT 21H
RET
CHANG ENDP
CODE ENDS
END BEG
● 运行结果:
二、统计数字【实验内容二】
● 题目描述:设计一个汇编程序,要求在数据段中预存放 10 个字符,统计 ASCII 码在 42H~45H 之间的字符个数并且以 8 位二进制的形式显示在屏幕上。
● 程序框图:
● 代码如下:
.586
DATA SEGMENT USE16
BUF DB 'NJUPT_ABC$'
COUNT EQU $-BUF ; 统计串的长度
TIM DB 0
DATA ENDS
CODE SEGMENT USE16
ASSUME CS:CODE, DS:DATA
BEG: MOV AX, DATA
MOV DS, AX
MOV BX, OFFSET BUF
MOV CL, COUNT ; 循环 COUNT 次
MOV DL, 0 ; 记录 42H~45H 之间的字符个数
FIRST: CMP BYTE PTR [BX], 42H
JC NEXT_1 ; < 42H 时转
CMP BYTE PTR [BX], 45H
JA NEXT_1 ; > 45H 时转
INC DL
NEXT_1: INC BX
DEC CL
JNZ FIRST
; ADD DL, 30H ; 将 DL 中存储的数字转化为 ASCII 码
;MOV AH, 2 ; 功能号02H(显示)
;INT 21H
MOV CX, 8 ; 8 位二进制显示
SECOND: MOV AL, '0' ; 0 的 ASCII 码
ROL DL, 1 ; (不含进位的循环)左移
JNC NEXT_2 ; 若当前 C 标志为 0 时, 则进行转移
MOV AL, '1' ; 1 的 ASCII 码
NEXT_2: MOV AH, 0EH ; 单字符显示
INT 10H
LOOP SECOND ; CX 将执行减 1 操作, 小于 0 时跳出循环
MOV AH, 4CH
INT 21H
CODE ENDS
END BEG
● 运行结果:
♦ 结果说明:42H 是 “B” 的 ASCII 码,45H 是 “E” 的 ASCII 码。“NJUPT_ABC$” 中有 2 个ASCII码在 42H ~ 45H 区间里面。
三、参考附录
[1] 《微型计算机原理与接口技术(慕课板)》
清华大学出版社
[2] 《汇编语言程序设计(第2版)》
[3] 《ASCII码一览表,ASCII码对照表》
链接: http://c.biancheng.net/c/ascii/.
[4] [bx]和bx有何区别?
链接: https://bbs.csdn.net/topics/30270849.
上一篇文章链接:【计算机与UNIX汇编原理⑧】——UNIX编程进阶【分支程序、循环程序、子程序、宏指令】.
下一篇文章链接:【计算机与UNIX汇编原理⑩】——汇编语言程序设计举例【三种进制转换】.
⭐️ ⭐️