一、 输出ASCII码表
- 思路:
将ASCII码值放在DL寄存器中,然后输出 - 源码:
MOV AH,02H ; 写DL中的数据到显示屏
MOV DL,01H ; 将十六进制ASCII码值放到DL
INT 21H ; 输出DL
- 应用
DATA SEGMENT
A DB 'Welcome to 8086','$'
B DB 'Please input GR code(0000~1111):$'
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE,DS DATA
START:
MOV AX,DATA ; 初始化DS段寄存器
MOV DS,AX
MOV DX,OFFSET A ; 获得字符串A的偏移地址
MOV AH,09H ; 显示字符串,直到遇到'$'停止(注意:DS要是段首地址,DX要是偏移地址)
INT 21H
; 实际应用在这一段
MOV AH,02H ; 写DL中的数据到显示屏
MOV DL,0AH ; 将换行符的ASCII码0AH放到DL中
INT 21H ; 输出DL中的数据
MOV DX,OFFSET B ; 获得字符串B中的偏移地址
MOV AH,09H ; 显示字符串B,知道遇到'$'停止(注意,DS要是段首地址,DX要是偏移地址)
INT 21H
MOV AX,4C00H ; 程序终止
INT 21H
CODE ENDS
END START
- 结果
二、实现格雷码到ASCII码的转换
- 思路:
格雷码的值作为下标,去GB中查表 - 源码:
DATA SEGMENT
A DB 'Welcome to 8086','$'
B DB 'Please input GR code(0000~1111)$'
GR DB 0,1,3,2,6,7,5,4,12,13,15,14,10,11,9,8
MSG2 DB 13,10,'The GR code is :$'
C DB 'I'M IN NANJING NORMAL UNIVERSITY','$'
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA
START:
MOV AX,DATA ; 初始化DS
MOV DS,AX
MOV DX,OFFSET A ; 取字符串A的偏移地址
MOV AH,09H ; 输出字符串A
INT 21H
FIRST:
MOV AH,02H ; 写DL中的数据到显示屏
MOV DL,0AH ; 打印换行符
INT 21H
MOV DX,OFFSET B ; 获取字符串B的偏移地址
MOV AH,09H ; 输出字符串B
INT 21H
MOV BX,0 ; BX初始化,BX用来保存用户输入的格雷码
MOV CX,4 ; CX用来控制循环次数 循环次数为4 格雷码的长度
_IN:
MOV AH,01H ; 读键盘输入到AL中并回显
INT 21H
CMP AL,13 ; 判断是否是回车键(注意:这一段代码是很好的,可以让用户输入的格雷码长度小于等于4)
JE SEARCH ; 跳
ADD BX,BX ; 将和左移一位,相当于乘以2
CMP AL,'0' ; 判断输入的字符是否是'0'
JE _0_
CMP AL,'1' ; 判断输入的字符是否是'1'
JE _1_
JMP FIRST ; 既不是回车,结束输入,也不是0或1,返回FIRST 重新输入
_1_:
INC BX ; AL是1,BX+1,返回上面左移一位
_0_:
LOOP _IN: ; AL是0,BX+0,返回上面左移一位
SEARCH:
MOV SI,0 ; 初始化SI=0
; 这一步查表还不太清楚
S1:
CMP BL,GR[SI]
JE DISP ; 如果成功发现,跳转DISP
INC SI ; 如果没有成功 一个个往下找
JMP S1
DISP:
MOV DL,10 ; 将换行写入显示屏
MOV AH,02H
INT 21H
MOV DL,13 ; 将回车写入显示屏
MOV AH,02H
INT 21H
MOV DX,OFFSET MSG2 ; 获取字符串MSG2的偏移地址
MOV AH,09H ; 打印字符串MSG2
INT 21H
; 对SI除10取余操作
MOV AX,SI
MOV CX,0
; D1模块:除10取余数操作
D1:
MOV AH,0
MOV BL,10
DIV BL ; DIV指令 除以字节 AL=商 AH=余数 除以字 AX=商 DX=余数
MOV DL,AH ;
PUSH DX
INC CX
CMP AL,0
JNE D1
; 压栈,压的是余数
D2:
POP DX ; 将数字转成ASCII码字符输出
ADD DL,30H
CMP DL,3AH
JB D3
ADD DL,02H ;这个地方还不太清楚
SUB CX,1 ; 如果增加这个,那么就是 100
; 如果不增加这个 那么就是1033
D3:
MOV AH,02H ; 读DL寄存器中的数据到屏幕上
INT 21H
LOOP D2
MOV AH,4CH
INT 21H
CODE ENDS
- 结果
- 上面代码中等以下还不懂。
- 比如用户输入了0011,实际的值是3,对应的是八进制的字符2,为什么比较的是BX(3)和GB[SI],而不是直接和下标SI进行比较呢?
- 猜想,是否GB中的表格是以字节方式存储的,所以BL是二进制数据,要对二进制数据转成10进制,输出方便用户查看?
- 调试SI寄存器,将SI寄存器的值放在AX,分别取AL,AH放到DL中,然后输出到屏幕,结果如下:
- 结果:
输出两个笑脸,不知道为什么。 - 实际参与运算的是BL:
始化时:
MOV BL,0 (原:MOV BX,0)
运算时:
ADD BL,BL (原:ADD BX,BX)
- 明确BL是二进制表示的格雷码,格雷码要和GR[SI]比较,为什么不直接和SI比较呢?
- 明白了 将二进制转成10进制那一段代码是比较好的。
- 有个疑问就是二进制转成十进制,加上了30H,就可以变成了ASCII码?
- 参考资料
- 最终明白了,格雷码放在数组里面,对应的下标,是其真正的值;
- 原来的想法,格雷码的真实值作为下标,格雷码的ASCII码值对应数组的值。
- 遇到问题:
上述代码运行的时候,如果刚好输入满足整除条件,结果会多0
还有高位低位的问题。
解决这两个问题 应该就能完成实验1.4了。
三、将ASCII码转成二进制输出
- 学习体会,初始化DL,打印在屏幕上,能够输出ASCII码表,说明DOXBox内置有ASCII码表
- 疑问:汇编指令内部,是如何存储数据的?直接二进制还是二进制的补码呢?
- 疑问: 如果要将ASCII转成十进制,又如何转换呢?是用循环移位指令?RCL还是逻辑移位指令,还是除法指令呢?
四、知识补充
- 格雷码有4位典型格雷码,也有八位格雷码。
- 用户输入的数字是ASCII码值,也可以用字符来代替。输入0,比较的是’0’字符0,输入1,比较的是’1’字符。也可以比较ASCII码值。
_IN:
MOV AH,01H ; 读键盘输入到AL中并回显
INT 21H
CMP AL,13 ; 判断是否是回车键(注意:这一段代码是很好的,可以让用户输入的格雷码长度小于等于4)
JE SEARCH ; 跳
CMP AL,'0' ; 判断输入的字符是否是'0'
JE _0_
CMP AL,'1' ; 判断输入的字符是否是'1'
JE _1_
- 第一个比较的是回车,用的是回车的ASCII码值13
- 第二个比较的是输入的数字,用的是0和1的字符形式,字符’0’,字符’1’。
四、总结
- 程序终止的两种办法
MOV AH,4CH
INT 21H
MOV AX,4C00H
INT 21H
反思:程序终止只跟高位AH有关
2. 程序开始要写
CODE SEGMENT
ASSUME CS:CODE
START:
代码块
CODE ENDS
END START
否则会出现错误:
4.
五、参考资料
- 80x86汇编语言编程:输入格雷码、输出对应的十进制数字
https://blog.csdn.net/baidu_33836580/article/details/50578944- 数字 0 - 9 转换成对应的格雷码
https://blog.csdn.net/baidu_33836580/article/details/50578833- 格雷码与二进制码的转换
https://blog.csdn.net/hanghang121/article/details/23927465- 汇编学习小记(三)-查表
https://juejin.im/post/5adb2c57f265da0b7451bdf0- 用汇编语言编写程序打印ASCII表
https://blog.csdn.net/ljianhui/article/details/17273431- 回车、换行、空格的ASCII码值—(附ASCII码表)
https://blog.csdn.net/songjinshi/article/details/7868866