描述单元长度的标号
之前一直在代码段中使用标号来标记指令、数据、段的起始地址。例如:
以上的 s1
、s2
、start
和 strdup
都是标号,这些标号仅仅表示了内存单元的地址。
还可以使用一种标号,这种标号不但表示内存单元的地址,还表示了内存单元的长度,即表示在此标号处的单元,是一个字节单元、字单元还是双字单元。这种标号的格式中标号名后面没有冒号“ :
”,例如:
这里的标号 s1
和 s2
,是同时描述内存地址和单元长度的标号:
- 标号
s1
描述了地址codes:0
,和从这个地址开始以后的内存单元都是字节单元; - 标号
s2
描述了地址codes:8
,和从这个地址开始以后的内存单元都是字单元。
这种标号包含了对单元长度的描述,在指令中它可以代表一个段中的内存单元。
对该标号地址的引用:
可以直接包含对单元长度的描述,相当于指令“ mov word ptr cs: [8], 2
”。
这种标号称为数据标号,它标记了存储数据单元的地址和长度,不同于仅仅表示地址的地址标号。数据标号可以以简洁的形式访问内存中的数据。
在其它段中使用数据标号
一般不在代码段中定义数据,而将数据定义放到其它段中。在其它段中也可以使用数据标号来描述存储数据的单元的地址和长度。
注意,在后面带有“ :
”的地址标号,只能在代码段中使用,不能在其它段中使用。
以下程序将 datas
段中中 items
标号处的8个数据累加,结果存到 total
标号处的字中:
如果在代码段中直接用数据标号访问数据,则需要用伪指令 assume 将标号所在的段和一个寄存器联系起来,以此确定标号的段地址在哪一个段寄存器内。在实际代码中,只需要将段地址移到对应的寄存器上即可。
在代码段中,可以使用数据标号直接访问数据:
可以将标号当做数据来定义,此时,编译器将标号所表示的地址当做数据的值。例如:
如果将标号当做数据,那么如果它被存储在字型数据中,实际上存储的是标号的偏移地址;如果被存储在双字型数据中,它实际上存储的是标号的偏移地址和段地址。低地址字存储偏移地址,高地址字存储段地址。
类似于 offset 操作符,可以使用 seg 操作符来取某一数据标号或地址标号的段地址。
直接定址表
可以利用表在两个数据集合之间建立一种映射关系,用查表的方法根据给出的数据得到其在另一集合中的对应数据。这样做的目的一般有3个:
- 为了算法的清晰和简洁
- 为了加快运算速度
- 为了使程序易于扩充
以下使用查表的方式,计算部分特殊角的三角函数正弦值。程序占用一部分内存空间来换取运算速度,将所要计算的结果存储在一张表中:
以下利用角度值除以30来作为相对 sin_table
的偏移,通过查表的方式取对应字符串的偏移地址,放在 BX 寄存器中:
类似于以上这种可以通过依据数据,直接计算出所要找的元素的位置的表,称为直接定址表。
也可以在直接定址表中存储子程序的地址,从而方便地实现不同子程序的调用。
例如,如果有以下子程序:
; ...code...
sub2:
; ...code...
sub3:
; ...code...
可以将这些功能子程序的入口地址存储在一个表中,它们在表中的位置和功能号相对应,可以直接通过查表的方式来选择对应功能:
; ...
call word ptr case[bx]
用根据功能号查找地址表的方法,程序的结构清晰,便于扩充。如果加入一个新的功能子程序,只需在地址表中加入它的入口地址即可。
使用BIOS进行磁盘读写
以3.5英寸软盘为例:
3.5英寸软盘分为上下两面,每面有80个磁道,每个磁道又分为80个扇区,每个扇区的大小为512个字节。故3.5英寸磁盘的存储大小为1440KB,或大约1.4MB。
磁盘的实际访问由磁盘控制器进行,可以通过控制磁盘控制器来访问磁盘。只能以扇区为单位对磁盘进行读写,在读写扇区的时候,要给出面号、磁道号和扇区号。面号和磁道号从0开始,而扇区号从1开始。
如果通过直接控制磁盘控制器来访问磁盘,需要涉及许多硬件细节。BIOS提供了 INT 13H
中断例程对磁盘进行访问,其入口参数为:
- AH :该中断例程的功能号,设置为2表示读取扇区;
- AL :读取的扇区数;
- CH :磁道号;
- CL :扇区号;
- DH :磁头号(对于软盘等同面号,因为一个面用一个磁头来读写);
- DL :驱动器号。软驱从0开始,0代表软驱A,1代表软驱B,以此类推。硬盘从80H开始,80H代表硬盘C,81H代表硬盘D,以此类推;
- ES : BX 指向接收从扇区读入数据的内存区。
其返回值为:
- 操作成功,则
(AH)=0
,(AL)
=读入的扇区数; - 操作失败,则
(AH)
=出错代码。
同样可以使用 INT 13H
中断例程将内存中的数据写入磁盘。其入口参数为:
- AH :该中断例程的功能号,设置为3表示对扇区写入数据;
- AL :写入的扇区数;
- CH :磁道号;
- CL :扇区号;
- DH :磁头号(面号);
- DL :驱动器号。
- ES : BX 指向将写入扇区的数据内存区。
其返回值为:
- 操作成功,则
(AH)=0
,(AL)
=写入的扇区数; - 操作失败,则
(AH)
=出错代码。
注意,在使用 INT 13H
中断例程时要注意驱动器号是否正确,不要随意对硬盘中的扇区进行写入。
以下程序将当前屏幕上的内容保存在磁盘上:
1屏的内容占4000个字节,需要8个扇区,因此用0面0道的1~8扇区存储显存中的内容。