这篇文章中,我们将讨论如何有效合理的组织数据,以及相关的编程技术.

一、描述了单元长度的标号

首先,我们来看一个简单的例子:

assume cs:code
code segment

a:  db 1,2,3,4,5,6,7,8,9
b:  dw 0
start:  
    mov si,offset a
    mov di,offset b
    mov cx,9
s:  mov al,cs:[si]
    mov ah,0
    add cs:[di],ax
    inc si
    loop s

    mov ax,4c00h
    int 21h
code ends
end start

不难看出上面程序是将a标号处的9个数据累加,结果存在b标号中的字中.程序中,code,a,b,start,s都是标号,这些标号仅仅表示了内存单元的地址.但是,我们还可以使用一种标号,这种标号不但表示内存单元的地址,还表示了内存单元的长度,即表示在此标号处的单元,是一个字节单元,还是字单元,还是双字单元,上面程序还可以这样写:

assume cs:code
code segment

a   db 1,2,3,4,5,6,7,8,9
b   dw 0
start:  
    mov si,0
    mov cx,9
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:9,和从这个地址开始,以后的内存单元都是字单元.

因为这种标号包含了对单元长度的描述,所以在指令中,它可以代表一个段中的内存单元,比如对于程序中的“b dw 0”

  • 指令 mov ax,b  相当于mov ax,cs:[9]
  • 指令 mov b,2   相当于 mov word ptr cs:[9],2
  • 指令 inc b        相当于 inc word ptr cs:[9]

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

下面指令会引起编译错误:

mov al,b

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

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

可见这种包含单元长度的标号,可以使我们以简洁的形式访问内存中的数据.

下面程序将code段中a处的8个数据累加,结果存在b处的双字中:

assume cs:code
code segment

a   dw 1,2,3,4,5,6,7,8
b   dd 0
start:  
    mov si,0
    mov cx,8
s:      
    mov ax,a[si]
    add word ptr b[0],ax
    adc word ptr b[2],0
    add si,2
    loop s

    mov ax,4c00h
    int 21h
code ends
end start

二、在其它段中使用数据标号

一般来说,我们不在代码段中定义数据,而是将数据定义到其它段中.在其它段中我们也可以使用数据标号来描述存储数据的单元的地址和长度.注意:在后面加有":"的地址标号,只能在代码段中使用,不能在其它段中使用.

下面面程序是将a标号处的8个数据累加,结果存在b标号中的字中:

assume cs:code
assume 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
    mov ah,0
s:      
    mov al,a[si]
    add b,ax
    add si,1
    loop s

    mov ax,4c00h
    int 21h
code ends
end start

注意,如果想在代码段中直接用数据标号访问数据,则需要用伪指令assume将标号所在的段和一个段寄存器联系起来.否则编译器在编译的时候,无法确定标号的段地址在哪一个寄存器中.当然这种联系是编译器需要的,不是说编译器会自动给我们设置ds段的值.

我们可以将标号作为数据来定义:

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

相当于:

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

相当于:

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

三、使用直接定址表输出16进制

assume cs:code
assume ds:data
data segment
    table db '0123456789ABCDEF'
data ends
code segment

start:  
    mov ax,data
    mov ds,ax
    mov cx,4
    mov ax,0FE1AH

s:  mov bx,0
    mov bl,ah
    and bl,0F0H;
    shr bl,1
    shr bl,1
    shr bl,1
    shr bl,1
    push ax
    mov dl,table[bx]
    mov ah,2
    int 21H
    pop ax
    shl ax,1
    shl ax,1
    shl ax,1
    shl ax,1
    loop s
    mov ax,4c00h
    int 21h
code ends
end start

可以看出,这个就像高级语言的数组

 

 

分类: 编程