问题一:刚开始的代码段作用和ASSUME不是等同?
问题二: DATA A B的区别?
一、XLAT查表指令
1. 指令作用
把待查表格的一个字节内容送到AL累加器中。
2. 使用方式
- 初始化BX (段首地址)
- 初始化AL (偏移地址)
- 查表 XLAT
3. 使用举例
MOV BX = X ; 初始化BX首地址
MOV AL = 03H ; 给定偏移地址AL
XLAT ; 查表XLAT
4. 注意细节
- BX中存放段首地址,段首地址可以是DS,也可以是用户定义的DATA;
- xlat查表指令只能是字节操作;每次偏移一个字节;
- BX是16位寄存器,AL是8位寄存器,偏移地址AL只有8位二进制,所以表格的最大容量是256字节;
- 举例:
在下面的例子中,就是将DB(DB作为汇编语言中的伪操作命令,它用来定义操作数占用的字节数。B代表的是BYTE字节,8位,而W代表的是WORD字,16位),
DATA SEGMENT
A DB 'HELLO WORLD','$' ;'$'作为停止符
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA
START:
MOV AX,DATA
MOV DS,AX ; 为什么要执行这一段代码,有待解决
LEA BX,A ; 数组偏移地址放入BX
MOV CL,00H ; 中转量
mov AL,CL
ONE:
XLAT; ; 查表
CMP AL,'$'
JZ END1
MOV DL,AL ; output character
MOV AH,02H
INT 21H
INC CL
MOV AL,CL
JMP ONE
END1: ; ending
MOV AX,4C00H
INT 21H
CODE ENDS
END START
5. 遇到问题
- DATA的值和数据段首A或者数据段首B的值有什么区别呢?
为什么对DATA的操作和对A的操作不一样
MOV AX,DATA ; 对DATA
MOV DS,AX
LEA BX,A ; 对A
- 解决办法
ASSUME是必须的,ASSUME指定段首地址,只是逻辑上关联,数值还没有装入;
A或B都是偏移地址;
在段首地址DS的基础上,偏移A,偏移B,成为BX段首地址;
通过AL偏移量,来输出数组。 - 参考资料
A. 汇编assume 伪指令
https://blog.csdn.net/u010234808/article/details/38366943
B. 关于汇编中ASSUME的讨论
https://blog.csdn.net/ll2323001/article/details/7597963
二、LEA指令
1. 指令功能
LEA指令是一个计算机指令,可以将有效地址传送到指定的的寄存器。
2. 使用指令
DATA SEGMENT ; 定义数据段
A DB 'HELLO WORLD','$' ;'$'作为停止符
B DB 'I AM IN NANJING NORMAL UNIVERSITY!','$' ;'$'作为停止符
DATA ENDS
START: ; 初始化
MOV AX,DATA
MOV DS,AX
LEA BX,A ; 将数据段A的地址传送给BX
; 或者传送数据段B给BX
; LEA BX,B
MOV CL,00H ; 中转量
mov AL,CL
ONE:
XLAT; ; 查表
CMP AL,'$'
JZ END1
MOV DL,AL ; 输出字符
MOV AH,02H
INT 21H
INC CL
MOV AL,CL
JMP ONE
END1: ; 程序终止
MOV AX,4C00H
INT 21H
CODE ENDS
END START
如果将B的数据段传送给BX,打印结果如下图:
3. 猜想
- 数据传送指令LEA既然是把地址送给了BX,为什么不能用MOV指令呢?将LEA指令修改成MOV指令。
DATA SEGMENT ; 定义数据段
A DB 'HELLO WORLD','$' ;'$'作为停止符
B DB 'I AM IN NANJING NORMAL UNIVERSITY!','$' ;'$'作为停止符
DATA ENDS
START: ; 初始化
MOV AX,DATA
MOV DS,AX
MOV BX,B ; 将数据段B的地址传送给BX,注意:这里用的是MOV而不是LEA传送
MOV CL,00H ; 中转量
mov AL,CL
ONE:
XLAT; ; 查表
CMP AL,'$'
JZ END1
MOV DL,AL ; 输出字符
MOV AH,02H
INT 21H
INC CL
MOV AL,CL
JMP ONE
END1: ; 程序终止
MOV AX,4C00H
INT 21H
CODE ENDS
END START
- 实验结果成功,如下图:
- 比较LEA指令和MOV指令
MOV指令,传送数据
LEA指令,取偏移地址
lea eax,[ebx+8] ; eax=ebx+8 是将ebx+8这个值直接赋给eax,
; 而不是把ebx+8处的内存地址里的数据赋给eax。
mov eax,[ebx+8] ; eax=[ebx+8] 是把内存地址为ebx+8处的数据赋给eax。
三、DB指令
- DB : DefineByte,定义字节类型变量,每个字节占1个字节;
四、DW指令
- DW : DefineWord,定义字类型变量,每个字占2个字节;
五、DD指令
- DD :DefineDouble,定义双字类型变量,每个双字占4个字节;
五、总结
- 查表指令使用要经过的阶段
- 定义数据段(DB DW DD )或堆栈段(SS)
- 确定段首地址(MOV LEA)
- 确定偏移地址(MOV)
- 查表(XLAT)
五、 学习中遇到的问题:
- 是所有的寄存器初始化下面状态码?
AX = FFFF
BX = 0000
CX = 0033
DX = 0000
SP = 0000
BP = 0000
SI = 0000
DI = 0000
DS = 075C
ES = 075C
SS = 076B
CS = 076D
IP = 0000
- ASSUME指令的作用是什么?
答:告诉编译器哪一个段和哪一个段寄存器相关联。
- assume为我们指定默认的段寄存器
- 若不使用assume,那么我们在程序中访问数据时必须人为地明确指定相应的段寄存器
- ASSUME指令如何应用呢?
在SEGMENT段内给段寄存器赋值
DATA SEGMENT
A DB 'HELLO WORLD','$';'$'作为停止
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA ; 将DATA段首地址存放在DS段寄存器当中
; 将CODE段首地址存放在CS段寄存器当中
START:
MOV AX,DATA
MOV DS,AX
LEA BX,A;数组偏移地址放入BX
MOV CL,00H;中转量
MOV AL,CL
ONE:
XLAT;查表
CMP AL,'$'
JZ END1
MOV DL,AL;输出字符
MOV AH,02H
INT 21H
INC CL
MOV AL,CL
JMP ONE
END1: ;结束
MOV AX,4C00H
INT 21H
CODE ENDS
END START
- ASSUME已经将DS段与DATA段连接起来了,为什么还要两行代码?
START:
MOV AX,DATA
MOV DS,AX
尝试数据段汇编:
- 源码
DATA SEGMENT
X DB 11H,22H,33H,44H,55H,66H,77H,88H
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA
START:
MOV AX,DATA
MOV DS,AX
LEA BX,X
MOV AL,01H
XLAT
MOV DL,AL ; output number
MOV AH,09H
INT 21H
CODE ENDS
END START
- 出现错误,没有数据显示
补充:查表指令学习网站:
ASCII码表
https://baike.baidu.com/item/ASCII/309296
格雷码与二进制的转换
https://blog.csdn.net/a493823882/article/details/80899042
请教8086汇编查表指令 XLAT
https://zhidao.baidu.com/question/120436271.html
XLAT指令
https://baike.baidu.com/item/XLAT%E6%8C%87%E4%BB%A4/4144842
汇编学习小记(三)-查表
https://juejin.im/post/5adb2c57f265da0b7451bdf0