直接定址表

Tutorial: 汇编基础 Category: C语言 Published: 2026-04-07 13:58:26 Views: 20 Likes: 0 Comments: 0
1. 程序中,code、a、b、start、s 都是标号。这些标号仅仅表示了内存单元的地址
assume cs:code
; 把 a 中的各数相加放到 b 里
code segment
        a:    db   1,2,3,4,5,6,7,8        ;在后面加有 :的地址标号,只能在代码段中使用,不能在其他段中使用。
        b:    dw   0

        ; -d cs:0
        ; 0E24:0000  01 02 03 04 05 06 07 08-01 00 BE 00 00 BB 08 00   ................

        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

        ; AX=0008  BX=0008  CX=0000  DX=0000  SP=0000  BP=0000  SI=0008  DI=0000
        ; DS=0E14  ES=0E14  SS=0E23  CS=0E24  IP=001E   NV UP EI PL NZ NA PO NC
        ; 0E24:001E B8004C        MOV     AX,4C00
        ; -d cs:0
        ; 0E24:0000  01 02 03 04 05 06 07 08-24 00 BE 00 00 BB 08 00   ........$.......

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


2. 描述了单位长度的标号
assume cs:code
code segment
        ; 标号a、b后面没有":",因此它们是可以同时描述内存地址和单元长度的标号。
        a     db   1,2,3,4,5,6,7,8
        ; 标号a,描述了地址code:0,和从这个地址开始,以后的内存单元都是字节单元
        ; 标号b描述了地址code: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
3. 使用数据标号来描述存储数据的单元的地址和长度
assume cs:code,ds:data ; 用伪指令assume将标号所在的段和一个段寄存器联系起来(编译器需要)

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           ; 真正确定ds寄存器
        ; -d ds:0
        ; 0E24:0000  01 02 03 04 05 06 07 08-00 00 00 00 00 00 00 00
              mov  si,0
              mov  cx,8

        s:    mov  al,a[si]        ; 编译为:mov al,[si+0] 默认所访问单元的段地址在ds
              mov  ah,0
              add  b,ax            ; 编译为:add [8],ax
              inc  si
              loop s
              mov  ax,4c00h
              int  21h
code ends
end start
data segment
	a db 1,2,3,4,5,6,7,8
	b dw 0
	c dw a, b ;等价于c dw offset a, offset b
	;数据标号c处存储的两个字型数据为标号a、b 的偏移地址
data ends

data segment
	a db 1,2,3,4,5,6,7,8
	b dw 0
	c dd a,b ;等价于c dw offset a, seg a, offset b, seg b
	;数据标号c处存储的两个双字型数据为标号a的偏移地址和段地址、标号b 的偏移地址和段地址
data ends


比如:
data segment
        x    db 1
        a    db 1,2,3,4,5,6,7,8        ; 偏移地址 0001
        b    dw 9999H                  ; 偏移地址 0009
        m    dw a,b                    ; 0001 0009

        ; -d ds:0
        ; 0E24:0000  01 01 02 03 04 05 06 07-08 99 99 01 00 09 00 00
data ends
4. 检测点 16.2
assume cs:code,es: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  es,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
5. 以 16 进制形式在屏幕中间显示给定的字节型数据
; 以16进制形式在屏幕中间显示给定的字节型数据
assume cs:codesg

codesg segment
        start:   mov  al, 0ABH
                 call showbyte

                 mov  ax, 4c00h
                 int  21h

        ; ---------------------------------------------
        showbyte:jmp  short show

        table    db   '0123456789ABCDEF'                                    ; 字符表

        show:    push ax
                 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  bl, al
                 mov  bh, 0
                 mov  al, table[bx]                                         ; 用低 4 位的值作为相对于 table 的偏移,取得相对应的字符

                 mov  bx, 0B800H
                 mov  es, bx

                 mov  byte ptr es:[160 * 12 + 40 * 2 + 0], ah
                 mov  byte ptr es:[160 * 12 + 40 * 2 + 1], 00000111B
                 mov  byte ptr es:[160 * 12 + 40 * 2 + 2], al
                 mov  byte ptr es:[160 * 12 + 40 * 2 + 3], 00000111B

                 pop  es
                 pop  bx
                 pop  ax

                 ret

codesg ends
end start
; 方法2
assume cs:code

code segment
        start:
                 mov  al,0ABH
                 call showbyte

                 mov  ax,4c00h
                 int  21h

        ; 子程序:
        ; 用al传送要显示的数据

        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的偏移,取得对应的字符 table[000A] = A = 41H

                 mov  bx,0b800h
                 mov  es,bx
                 mov  es:[160*12+60*2],ah

                 mov  bl,al
                 mov  bh,0
                 mov  al,table[bx]                 ; 用低4位的值作为相对于table的偏移,取得对应的字符 table[000B] = B = 42H

                 mov  es:[160*12+60*2+2],al

                 pop  es
                 pop  bx
                 ret

code ends
end start
6. 计算 sin(x),使用直接定址表
; 编写一个子程序,计算 sin(x) = {0,30,60,90,120,150,180}
; 并在屏幕中间显示计算结果。比如 sin(30)显示为"0.5"

assume cs:codesg

codesg segment
        start:   mov  ax, 0
                 mov  al, 120

                 call sin

                 mov  ax, 4c00h
                 int  21h


        ; ---------------------------------------------
        sin:     jmp  _show                                             ; 01    23    45    67     89     1011   1012
        table    dw   ag0, ag30, ag60, ag90, ag120, ag150, ag180        ; 字符串偏移地址表
        ag0      db   '0', 0
        ag30     db   '0.5', 0
        ag60     db   '0.866', 0
        ag90     db   '1', 0
        ag120    db   '0.866', 0
        ag150    db   '0.5', 0
        ag180    db   '0', 0

        _show:   push bx
                 push es
                 push si

                 mov  bx ,0B800H
                 mov  es, bx

        ; 用 角度/30 作为相对于 table 的偏移,取得对应字符串的偏移地址,放在 bx 中
                 mov  ah, 0
                 mov  bl, 30
                 div  bl

        ; 判断部分,如果是奇奇怪怪的角度直接退出
                 cmp  ah, 0
                 jne  _retShow

                 mov  bl, al
                 mov  bh, 0
                 add  bx, bx                                            ; 因为是 dw 类型的所以要 乘以2,一个偏移地址占 2 个字节
                 mov  bx, table[bx]                                     ; table[0008] = 2B

        ; 以下显示 sin(x) 对应字符串
                 mov  si, 160 * 12 + 40 * 2
        _shows:  mov  ah, cs:[bx]
                 cmp  ah, 0
                 je   _retShow
                 mov  byte ptr es:[si + 0], ah
                 mov  byte ptr es:[si + 1], 00001111B
                 inc  bx
                 add  si, 2
                 jmp  short _shows
        _retShow:pop  si
                 pop  es
                 pop  bx
                 ret
codesg ends
end start
Prev: 实验15 Next: 实验16