11. 直接定址表

99 阅读4分钟

直接定址表

这一章,我们讨论如何有效合理地组织数据,以及相关的编程技术。

1. 描述了单元长度的标号

之前,我们一直在代码段中使用标号来标记指令、数据、段的起始地址。比如,下面的程序将code段中的a标号处的8割数据累加,结果存储到b标号处的字中。

 assume cs:code
 code segment
      a: db 1, 2, 3, 4, 5, 6, 7, 8
      b: dw 0
      
  start: mov si, offset a
         mov bx, offset b
         mov cx, 8
      s: mov al, cs:[si]
         mov ah, 0
         add cs:[bx], ax
         inc si
         loop s
         
         mov ax, 4c00H
         int 21H
 code ends
 end start

程序中,code、a、b、start、s都是标号。这些标号仅仅表示了内存单元的地址。

但我们可以使用一种标号,这种标号不但表示内存单元的地址,还表示了内存单元的长度,即表示在次标号的单元,是一个字单元还是双字单元。 上面的程序还可以写成这样:

 assume cs:code
 code segment
      a db 1, 2, 3, 4, 5, 6, 7, 8
      b dw 0
      
 start: mov si, 0
        mov cx, 8
     s: mov al, a[si]
        mov ah, 0
        add b, ax
        inc si
        loop s
        
        mov ax, 4c00H
        int 21H
 code ends
 end start

2. 在其它段中使用数据标号

一般来说,我们不在代码段中定义数据,而是将数据定义到其它段中。在其它段中,我们也可以使用数据标号来描述存储数据的单元的地址和长度。

注意:在后面加有":"的地址标号,只能在代码段中使用,不能在其它段中使用。

下面的程序将data段中a标号处的8个数据累加,结果存储到b标号处的字中。

 assume cs:code ds:data
 data segment
      a db 1, 2, 3, 4, 5, 6, 7, 8
      b dw 0
 data ends
 ​
 code segment
  start: mov ax, data
         mov ds, ax
         
         mov si, 0
         mov cx, 8 
      s: mov al, a[si]
         mov ah, 0
         add b, ax
         inc si
         loop s
         
         mov ax, 4c00H
         int 21H
 code ends
 end start

*注意:如果想在代码段中直接用数据标号访问数据,则需要用伪指令assume将标号所在的段和一个段寄存器联系起来。否则编译器在编译的时候,无法确定标号的段地址在哪一个寄存器中。*当然,这种联系时编译器需要的,但绝对不是说,我们因为编译器的工作需要,用assume指令将段寄存器和某个段联系起来,段寄存器中就会真的存放该段的地址。我们在程序中还要使用指令对段寄存器进行设置。

比如,在上面的程序中,我们要在代码段code中用data段中的数据标号a、b访问数据,则必须用assume将一个寄存器和data段相连。在程序中,我们用ds寄存器和data段相联,则编译器对相关指令的编译如下。

 指令:     mov al, a[si]
 编译为:   mov al, [si+0]
 ​
 指令:     add b, ax
 编译为:   add [8], ax

因为这些实际编译出的指令,都默认所访问单元的段地址在ds中,而实际要访问的段为data,所以若要访问正确,在这些指令执行前,ds中必须为data段的段地址。则我们在程序中使用指令。

 mov ax, data
 mov ds, ax

设置ds指向data段。

可以将标号当作数据来定义,此时,编译器将标号所表示的地址当作数据的值。

比如:

 data segment
   a db 1, 2, 3, 4, 5, 6, 7, 8
   b dw 0
   c dw a, b
 data ends

数据标号c处存储的两个字型数据为标号a、b的偏移地址。相当于:

 data segment
   a db 1, 2, 3, 4, 5, 6, 7, 8
   b dw 0
   c dw offset a, offset b
 data ends

再比如:

 data segment
   a db 1, 2, 3, 4, 5, 6, 7, 8
   b dw 0
   c dd a, b

数据标号c处存储的两个双字型数据为标号a的偏移地址和段地址、标号b的偏移地址和段地址。相当于:

 data segment
   a db 1, 2, 3, 4, 5, 6, 7, 8
   b dw 0
   c dw offset a, seg a, offset b, seg b
 data ends

seg操作符,功能为取得某一标号的段地址。