鱼C论坛

 找回密码
 立即注册
查看: 3408|回复: 0

[学习笔记] 直接定址表

[复制链接]
发表于 2017-12-7 22:06:11 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
16.1节   描述单元长度的标号

编程:将a标号的数据累加的结果放在b标号处
代码:
assume cs: code 


code segment 

        a:  db 1, 2, 3, 4, 5, 6, 7, 8
        b:  dw 0

start:                 mov si, offset b 
                                mov bx, offset a 
                                mov cx, 8
                                
                        s:        mov al, cs:[bx]
                                mov ah, 0
                                add cs:[si], ax
                                inc bx 
                                
                                loop s
                                
                                mov ax, 4c00H
                                int 21H
                                
code ends 
end start 

在程序中,code、a、b、s都是标号,这里仅表示内存单元的地址
但是我们可以用另外的标号,这种标号不但表示内存单元的地址,还表示内存单元的长度

上面的程序可以写下面的样子:
代码:
assume cs: code 

code segment 

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

可以看看与刚开始的程序不同的是a标号处没有冒号了,其他它的作用就是表示刚开始的地址和定义的长度
比如:
指令:mov al, a[bx]
相当于:mov al, cs:0[bx]

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

我们称这种标号为数据标号,它标记了存储数据单元的地址和长度

16.2节  在其他段使用数据标号


因为一般我们都不会定义数据在代码段中,所以我们将数据标号用于数据段

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

看这样的例子
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.3   直接地址表

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

步骤:
(1)将所在显示的字节放在al中
(2)将al的高位和低位分开,我这里分别放入ah和al中
(3)ah和al即为在table标号中的偏移
(4)将在table标号中ah偏移的字符放在bx中,然后让它在屏幕中央显示
()将在table标号中al偏移的字符放在bx中,然后让它在屏幕中央显示

具体代码:
assume cs: code 

code segment 

start:                        mov al, 2eH
                                call showbyte
                                
                                mov ax, 4c00H
                                int 21H
                                
showbyte:                jmp short show 
                                table                db '0123456789ABCDEF'
                                
        show:                push ax 
                                push bx 
                                push ds 
                                
                                mov ah, al
                                mov cl, 4 
                                shr ah, cl 
                                and al, 00001111b
                                
                                mov bl, ah 
                                mov bh, 0
                                mov ah, table[bx]
                                
                                mov ax, 0b800H
                                mov es, ax 
                                mov es:[12* 160 + 80], ah 
                                
                                mov bl, al 
                                mov bh, 0 
                                mov al, table[bx]
                                
                                mov ax, 0b800H
                                mov es, ax 
                                mov es:[12* 160 + 80 + 2], al
                                
                                pop ds
                                pop bx 
                                pop ax 
                                
                                ret 
                                
code ends 
end start 

                                
                                

编程:写一个子程序,计算sin(x), x = 0、30 、60、 90、120、150、180

大概流程跟上面的程序差不多,就是寻找table标号的偏移不一样,程序的方法是度数/30,然后将得到的数字自加,结果就是在table标号的偏移
具体代码:
assume cs:code

code segment
start:  
                mov al,60

        call showsin

        mov ax,4c00h
        int 21h

showsin:
        jmp short show
                
        table dw ag0,ag30,ag60,ag90,ag120,ag150,ag180        ;字符串偏移地址表
        ag0      db '0',0                        ;sin(0)对应的字符串“0”
        ag30     db '0.5',0                        ;sin(0)对应的字符串“0.5”
        ag60     db '0.866',0                        ;sin(0)对应的字符串“0.866”
        ag90     db '1',0                        ;sin(0)对应的字符串“1”
        ag120    db '0.866',0                        ;sin(0)对应的字符串“0.866”
        ag150    db '0.5',0                        ;sin(0)对应的字符串“0.5”
        ag180    db '0',0                        ;sin(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
        mov bl,al
        mov bh,0
        add bx,bx
        mov bx,table[bx]

;以下显示sin(x)对应的字符串
        mov si,160*12+40*2
shows:  
                mov ah,cs:[bx]
        cmp ah,0
        je showret
        mov es:[si],ah
        inc bx
        add si,2
        jmp shows

showret:
        pop si
        pop es
        pop bx
        ret

code ends

end start


像这种可以依据数据,直接计算出元素的位置的表,我们称其为:直接定定址表
16.4   程序入口地址的直接定址表

编程:编写子程序,实现如下功能:
(1)清屏
(2)设置前景色
(3)设置背景色
(4)向前滚动一行

说明,:用寄存器ah传递功能号:0表示清屏,1表示设置前景色,2表示设置背景色,3表示向前滚动
具体代码:
;编程:实现一个子程序setscreen,为显示输出提供如下功能:
;(1) 清屏。
;(2) 设置前景色。
;(3) 设置背景色。
;(4) 向上滚动一行。
;
;入口参数说明:
;(1) 用 ah 寄存器传递功能号:0 表示清屏,1表示设置前景色,2 表示设置背景色,3 表示向上滚动一行;
;(2) 对于2、3号功能,用 al 传送颜色值,(al) ∈{0,1,2,3,4,5,6,7}

setscreen: jmp short set

    table  dw sub1,sub2,sub3,sub4

set:        
        push bx        
        cmp ah,3                ;判断传递的是否大于 3
        ja sret
        mov bl,ah
        mov bh,0
        add bx,bx                ;根据ah中的功能号计算对应子程序的地址在table表中的偏移
        
        call word ptr table[bx]        ;调用对应的功能子程序

sret:        
        pop bx        
        iret

;功能子程序1:清屏
sub1:   
        push bx
        push cx
    push es
        mov bx,0b800h
        mov es,bx
        mov bx,0
        mov cx,2000
        
sub1s:  
        mov byte ptr es:[bx],' '
    add bx,2
    loop sub1s
    pop es
    pop cx
    pop bx
        ret ;sub1 ends

;功能子程序2:设置前景色
sub2:        
        push bx
        push cx
        push es
        mov bx,0b800h
        mov es,bx
        mov bx,1
        mov cx,2000
        
sub2s:        
        and byte ptr es:[bx],11111000b        
        or es:[bx],al 
        add bx,2
        loop sub2s

        pop es
        pop cx
        pop bx
        ret ;sub2 ends

;功能子程序3:设置背景色
sub3:        
        push bx
        push cx
        push es
        mov cl,4
        shl al,cl
        mov bx,0b800h
        mov es,bx
        mov bx,1
        mov cx,2000
        
sub3s:        
        and byte ptr es:[bx],10001111b
        or es:[bx],al 
        add bx,2
        loop sub2s

        pop es
        pop cx
        pop bx
        ret ; sub3 ends

;功能子程序4:向上滚动一行
sub4:        
        push cx
        push si
        push di
        push es
        push ds

        mov si,0b800h
        mov es,si
        mov ds,si
        mov si,160                        ;ds:si指向第n+1行
        mov di,0                        ;es:di指向第n行
        cld
        mov cx,24;共复制24行

sub4s:        
        push cx
        mov cx,160
        rep movsb                         ;复制
          pop cx
        loop sub4s

        mov cx,80        
        mov si,0
        
sub4s1: 
        mov byte ptr es:[160*24+si],' '                ;最后一行清空
        add si,2
        loop sub4s1

        pop ds
        pop es
        pop di
        pop si
        pop cx
        ret ;sub4 ends

在这里我们显然看到直接地址表的优势,如果想要加入一个新的子程序,只需要把它加入表中即可

评分

参与人数 1荣誉 +5 鱼币 +5 贡献 +3 收起 理由
兰陵月 + 5 + 5 + 3 热爱鱼C^_^

查看全部评分

本帖被以下淘专辑推荐:

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-25 04:07

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表