ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

汇编语言-17直接定址表

2020-10-22 12:01:09  阅读:197  来源: 互联网

标签:标号 code 17 汇编语言 定址 mov al 地址 data


单元长度的标号

在代码段中使用标号来标记指令、数据、段的起始地址。比如,下面的程序将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
    loops
    
    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

在code段中使用的标号a 、b后面没有":",它们是同时描述内存地址和单元长度的标号。标号a,描述了地址code:0, 和从这个地址开始,以后的内存单元都是字节单元;而标号b 描述了地址code:8, 和从这个地址开始,以后的内存单元都是字单元。

因为这种标号包含了对单元长度的描述,所以在指令中,它可以代表一个段中的内存单元。

比如,对于程序中的"b dw 0":

指令: mov ax,b
相当于: mov ax,cs:[8]

指令: mov b,2
相当于: mov word ptr cs:[8],2

指令: inc b
相当于: inc word ptr cs:[8]

在这些指令中,标号b代表了一个内存单元,地址为code:8, 长度为两个字节。

下面的指令会引起编译错误:
mov al,b
因为b代表的内存单元是字单元,而al是8 位寄存器。

对于程序中的"a db 1,2,3,4,5,6,7,8" :

指令: mov al,a[si]
相当于: mov al,cs:0[si]

指令: mov al,a[3]
相当于: mov al,cs:0[3]

指令: mov al,a[bx+si+3]
相当于: mov al,cs:0[bx+si+3]

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

在其他段中使用数据标号

一般来说,我们不在代码段中定义数据,而是将数据定义到其他段中。在其他段中,我们也可以使用数据标号来描述存储数据的单元的地址和长度。
注意,在后面加有":"的地址标号,只能在代码段中使用,不能在其他段中使用。下面的程序将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
data ends

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

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

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

直接定址表

用查表的方法编写相关程序的技巧。

编写子程序,以十六进制的形式在屏幕中间显示给定的字节型数据。

分析: 一个字节需要用两个十六进制数码来表示,所以,子程序需要在屏幕上显示两个ASCII 字符。我们当然要用“0" 、“1 "、“2" 、“3" 、“4" 、“5" 、“6" 、“ 7” 、“8" 、“9" 、“A" 、“B" 、“C" 、“D" 、“E" 、“F” 这16个字符来显示十六进制数码。

showbyte: jmp short show

        table db '0123456789ABCDEF'    ;字符表

   show: push bx
        push es
        
        mov ah,al
        shr ah,1
        shr ah,1
        shr ah,1
        shr ah,1     ;右移4位,ah中得到高4位的值
        and al, 00001111b    ;al中为低4位的值
        
        mov bl,ah
        mov bh,0
        mov ah,table[bx]    ;用高4位的值作为相对于table的偏移,取得对应的字符
        
        mov bx,0b800h
        mov es,bx
        mov es:(160*12+40*2),ah
        
        mov bl,al
        mov bh,0
        mov al,table[bx]    ;用低4 位的值作为相对于table的偏移,取得对应的字符
        
        mov es:[160*12+40*2+2],al
        
        pop es
        pop bx
        
        ret

可以看出,在子程序中,在数值0-15 和字符“O" ~ "F" 之间建立的映射关系为:以数值N为table表中的偏移,可以找到对应的字符。利用表,在两个数据集合之间建立一种映射关系,使我们可以用查表的方法根据给出的数据得到其在另一集合中的对应数据。这样做的目的一般来说有以下3个:
(1) 为了算法的清晰和简洁;
(2) 为了加快运算速度;
(3) 为了使程序易于扩充。

标签:标号,code,17,汇编语言,定址,mov,al,地址,data
来源: https://www.cnblogs.com/aeolian/p/13854211.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有