首页 > 代码库 > 直接定址表(学习汇编)

直接定址表(学习汇编)

1.我们可以使用一种标号,这种标号不但表示内存单元的地址,还表示了内存单元的长度,即表示在此标号处的单元,是一个字节单元,还是字单元,还是双字单元。如

  a:db 1,2,3,4,5,6,7,8             改写为    a   db   1,2,3,4,5,6,7,8

  b:dw  0                          改变为    b     dw   0

使用不带“:”的标号,它们是同时描述内存地址和单元长度的标号。这种标号包含了对单元长度的描述,所以,在指令中,它可以代表一个段中的内存单元。

2.使用这种包含单元长度的标号,可以使我们以简洁的形式访问内存中的数据。以后,我们将这种标号称为数据标号,它标记了存储数据的单元的地址和长度。它不同于仅仅表示地址的地址标号。

 

在其他段中使用数据标号

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

2.注意,在后面加有“:”的地址标号,只能在代码段中使用,不能再其他段中使用。

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

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

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

 

附上一个用直接定址表来计算sin(x)的程序:

 1 assume cs:code  2 code segment  3 start: 4         mov al,60 5         call showsin 6          7         mov ax,4c00h 8         int 21h 9         10 showsin:11         jmp short show 12         table dw ag0,ag30,ag60,ag90,ag120,ag150,ag18013         ag0 db 0,014         ag30 db 0.5, 0 15         ag60 db 0.866, 0 16         ag90 db 1,017         ag120 db 0.866,0 18         ag150 db 0.5,0 19         ag180 db 0,020         21 show :22         push bx23         push es24         push si 25         mov bx,0b800h26         mov es,bx 27         28         mov ah,0 29         mov bl,30 30         div bl 31         mov bl,al ;角度/30作为table偏移,商al放到bl中32         mov bh,0 33         add bx ,bx   ;因为dw每个占2字节,0-1,,1-2 ...34         mov bx,table[bx]35         mov si,160*23+40*236 shows:37         mov ah,cs:[bx]38         cmp ah,0     ;ah是否为0,是则跳转至showret39         je showret 40         mov es:[si],ah 41         inc bx 42         add si,243         jmp shows 44         45 showret:46         pop si 47         pop es 48         pop bx 49         ret 50         51         52         53 code ends54 end start