1、前面我们一直在代码段使用标号来标记指令、数据、段的起始位置。比如,
a:db 1,2,3,4,5,6,7,8
b:dw 0
程序中,a,b只是标号,它仅仅表示了内存单元的地址
但是,我们还可以使用一种标号,这种标号不但标识内存单元的地址,还表示了内存单元的长度,即表示在此标号的单元,是一个字节单元,还是字单元,还是双字单元
a db 1,2,3,4,5,6,7,8
b dw 0
在a b后面没有“:”,他们是同时描述内存地址和单位长度的标号。标号a,描述了地址code:0,和从这个地址开始,以后的内存单元都是字节单元;而标号b描述了地址code:8,和从这个地址开始,以后的内存单元都是字单元
在这里 标号b代表了一个内存单元,地址为xxxx:8,长度为两个字节
下面的指令会引起编译错误
mov al,b
因为b代表的内存单元是字单元,而al是8位寄存器
可见,使用这种包含单元长度的标号,可以使我们以简洁的形式访问内存中的数据。以后,我们将这种标号称为数据标号,他标记了存储数据的单元的地址和长度。它不同于仅仅表示地址的地址标号
2、在其他段中使用数据标号
一般来说,我们不在代码段中定义数据,而实将数据定义在其他段中。在其他段中,我们也可以使用数据标号来描述存储数据的单元的地址和长度。
注意,在后面加有“:”的地址标号,只能在代码段中使用,不能在其他段中使用
注意,如果想在代码段中直接使用数据标号来访问数据,则需要用伪指令assume将标号所在的段和一个段寄存器联系起来。否则编译器在编译的时候,无法确定标号的段地址在哪一个寄存器中。当然,这种联系是编译器需要的,但绝不是说,我们因为编译器的工作需要,用assume指令将段寄存器和某个段联系起来,段寄存器中就会真的存放该段的地址,我们在程序中还要使用指令对段寄存器进行设置
3、直接定址表
通过样例讨论查表的方法编写相关程序的技巧
编写子程序,以16进制的形式在屏幕中间显示给定的字节型数据
分析;一个字节需要用两个十六进制数码来表示,所以子程序需要在屏幕上显示两个ASCII字符,我们当然用0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F这十六个字符来显示十六进制数码
我们可以将一个字节的高四位和低四位分开,分别用他们的值得到对应的数码字符。比如2BH,可以的达奥高四位的值为2,低四位的值为11,那么如何用这两个数值得到对应的数码字符2和B呢
最简单的方法就是一个一个比较,但是这样做,程序中要使用多条比较,转移指令。程序将比较长,混乱
显然,我们希望能够在数值0~15和字符0~F之间找到一种映射关系。这样用0~15间的任何数值,都可以通过这种映射关系直接得到0~F中对应的字符
我们考虑一下ASCII与其之间的映射:
0~9之间的映射关系很明显 相差30H
A~F之间的映射关系也很明显 相差37H
可见,我们可以利用数值和字符之间的这种原本存在的映射关系,通过高四位和低四位值得到对应的字符码,但是由于映射关系的不同,我们在程序中必须做一些比较,对于大于9的数值,我们要用不同的计算方法
这样做,虽然程序得到了简化。但是,如果我们希望用更简洁的算法,就要考虑用同一种映射关系从数值得到字符码。所以,我们就不能利用他们与ASCII之间的对应关系了
因为数值0~15和字符0~F之间没有一直的映射关系存在,所以,我们应该在他们之间建立新的映射关系
具体的做法是,建立一张表,表中一次存储字符0~F,我们可以通过数值0~15直接查找到对应的字符
利用表,在两个数据集合中间建立一种映射关系,使我们可以用查表的方法根据给出的数据得到其在另一集合中的对应数据。这样做的目的一般来说有以下3个
(1)为了算法的清晰和简洁
(2)为了加快运算速度;
(3)为了是程序易于扩充