实验环境
- Intel 8086 CPU的汇编语言
- Masm611 和 debug 调试器
- DOSBox0.74 免费开源跨平台 MS-DOS 模拟器
题目
- 在屏幕上显示”What is your name?”,输入自己姓名后显示”My name is XXXX”。
第一版实验
实验结果
存在的问题
- 问题:实验结果有一点小瑕疵,最后输出的结果:My name is (这里会有一个乱码的字符)XXXXX,大家可以拿去源码运行,发现了问题在哪里,麻烦评论或者私信告诉我哦,感谢!!!
- 原因:
- 由于输入字符串的时候当前首地址用来存放该字符串可以存放的最大字符数,第二个位置用来存放当前实际存放的字符数,读取数据的时候会修改第二个位置的数值,然后第三个位置才开始读取字符串
- 所以真实姓名前多了一个非法的字符是实际字符数对应的 ASCII 对应的字符。
- 这里还有一个问题是,这里最多只能输入 32 个字符。
- 因为当前的首地址存储的是 一个 空格(ASCII码为32),将这个值作为了最大能够输入的字符数。
- 解决办法:将 “My name is ” 单独用一个字符串存放,读取的数据再单独用一个字符串来存放,见版本二。
源代码
;exp7_4.txt(文件名,分号后面就是注释)
.model small
.stack
.data ;定义数据段
string DB 'What is your name ?',0DH, 0AH, '$' ;字符串应当以 $ 符号结束,0DH, 0AH, 回车换行的作用
buffer DB 255, 14, 0DH, 0AH, 'My name is ' ; ;第一个字符存储该字符最多存储的字符数,第二个位置表示当前存储的字符个数
DB 200 DUP('$') ;确保字符串是以 $ 符号结尾的
.code
.startup ;程序起始点,建立DS、SS
;设置欲显示字符串在主存中的首地址
mov DX, seg string ;获取段地址,因为mov指令不能直接将立即数送到段寄存器中,所以使用中间寄存器
mov DS, DX
mov DX, offset string ;获取偏移地址
mov AH, 09H ;输出一个以DS:DX首地址开始,以$结尾的字符串
INT 21H
;读取一个字符串
mov DX, seg buffer
mov DS, DX
mov DX, offset buffer ;获取偏移地址
mov BX, DX ;因为寄存器相对寻址方式的基地址只能是 BX/BP
MOV AL, [BX + 1] ;获取到当前字符串实际已经存储的字符数,由于只占一个字节,所以使用AL
mov AH, 0H ;后面的 ADD DX, AX要求位数相匹配,不能直接和AL相加,所以将AH设置为0防止影响结果
ADD DX, AX ;获取已有字符串的末尾继续增加字符
mov AH, 0AH
INT 21H
;输出一个字符串
mov DX, offset buffer
ADD DX, 2
mov AH, 09H ;输出一个以DS:DX首地址开始,以$结尾的字符串
INT 21H
.exit 0
end
第二版实验
实验结果
源代码
;exp7_4.txt(文件名,分号后面就是注释)
.model small
.stack
.data ;定义数据段
string DB 'What is your name ?',0DH, 0AH, '$' ;字符串应当以 $ 符号结束,0DH, 0AH, 回车换行的作用
buffer DB 'My name is ', '$' ;确保字符串是以 $ 符号结尾的
input_str DB 255, 0
DB 253 DUP ('$')
.code
.startup ;程序起始点,建立DS、SS
;设置欲显示字符串在主存中的首地址
mov DX, seg string ;获取段地址,因为mov指令不能直接将立即数送到段寄存器中,所以使用中间寄存器
mov DS, DX
mov DX, offset string ;获取偏移地址
mov AH, 09H ;输出一个以DS:DX首地址开始,以$结尾的字符串
INT 21H
;读取一个字符串
mov DX, seg input_str
mov DS, DX
mov DX, offset input_str ;获取偏移地址
mov BX, DX ;因为寄存器相对寻址方式的基地址只能是 BX/BP
MOV AL, [BX + 1] ;获取到当前字符串实际已经存储的字符数,由于只占一个字节,所以使用AL
mov AH, 0H ;后面的 ADD DX, AX要求位数相匹配,不能直接和AL相加,所以将AH设置为0防止影响结果
ADD DX, AX ;获取已有字符串的末尾继续增加字符
mov AH, 0AH
INT 21H
;输出一个字符串
mov AH, 09H ;输出一个以DS:DX首地址开始,以$结尾的字符串
mov DX, offset buffer
INT 21H
LEA DX, input_str+2
INT 21H
.exit 0
end
总结
- 实验的关键要点都在源代码中的注释中,里面有很多的细节,大家可以阅读源代码。
- 输入字符串的时候第一个位置用来存储最大的字符数,第二个位置用来存储实际存储的字符数,第三个位置才开始读取输入的字符串, 并且会根据实际输入的字符数来修改第二个位置的值。
- 最大字符数是自己事先设置好了的,在输入字符的时候会判断是否超过了允许输入的最大字符数。