鱼C论坛

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

[学习笔记] 直接定址表

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

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

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

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

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


  2. code segment

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

  5. start:                 mov si, offset b
  6.                                 mov bx, offset a
  7.                                 mov cx, 8
  8.                                
  9.                         s:        mov al, cs:[bx]
  10.                                 mov ah, 0
  11.                                 add cs:[si], ax
  12.                                 inc bx
  13.                                
  14.                                 loop s
  15.                                
  16.                                 mov ax, 4c00H
  17.                                 int 21H
  18.                                
  19. code ends
  20. end start
复制代码


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

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

  2. code segment

  3.         a        db 1, 2, 3, 4, 5, 6, 7, 8
  4.         b        dw 0
  5.        
  6.         start:        mov cx, 8
  7.                                 mov bx, 0
  8.                         s:        mov al, a[bx]
  9.                                 mov ah, 0
  10.                                 add b, ax
  11.                                 inc bx
  12.                                
  13.                                 loop s
  14.                                
  15.                                 mov ax, 4c00H
  16.                                 int 21H
  17. code ends
  18. end start
复制代码


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

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

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

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


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

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

看这样的例子
  1. data segment

  2.         a        db 1, 2, 3, 4, 5, 6, 7, 8
  3.         b        dw 0
  4.         c         dw a, b
  5.        
  6. data ends
复制代码


相当于下面的代码:
  1. data segment

  2.         a        db 1, 2, 3, 4, 5, 6, 7, 8
  3.         b        dw 0
  4.         c         dw offset a, offset b
  5.        
  6. data ends
复制代码


再看下面的:
  1. data segment

  2.         a        db 1, 2, 3, 4, 5, 6, 7, 8
  3.         b        dw 0
  4.         c         dd a, b
  5.        
  6. data ends
复制代码


相当于下面的代码:
  1. data segment

  2.         a        db 1, 2, 3, 4, 5, 6, 7, 8
  3.         b        dw 0
  4.         c         dw offset a, seg a, offset b, seg b  
  5.        
  6. data ends
复制代码



16.3   直接地址表

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

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

具体代码:
  1. assume cs: code

  2. code segment

  3. start:                        mov al, 2eH
  4.                                 call showbyte
  5.                                
  6.                                 mov ax, 4c00H
  7.                                 int 21H
  8.                                
  9. showbyte:                jmp short show
  10.                                 table                db '0123456789ABCDEF'
  11.                                
  12.         show:                push ax
  13.                                 push bx
  14.                                 push ds
  15.                                
  16.                                 mov ah, al
  17.                                 mov cl, 4
  18.                                 shr ah, cl
  19.                                 and al, 00001111b
  20.                                
  21.                                 mov bl, ah
  22.                                 mov bh, 0
  23.                                 mov ah, table[bx]
  24.                                
  25.                                 mov ax, 0b800H
  26.                                 mov es, ax
  27.                                 mov es:[12* 160 + 80], ah
  28.                                
  29.                                 mov bl, al
  30.                                 mov bh, 0
  31.                                 mov al, table[bx]
  32.                                
  33.                                 mov ax, 0b800H
  34.                                 mov es, ax
  35.                                 mov es:[12* 160 + 80 + 2], al
  36.                                
  37.                                 pop ds
  38.                                 pop bx
  39.                                 pop ax
  40.                                
  41.                                 ret
  42.                                
  43. code ends
  44. end start

  45.                                
  46.                                
复制代码


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

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

  2. code segment
  3. start:  
  4.                 mov al,60

  5.         call showsin

  6.         mov ax,4c00h
  7.         int 21h

  8. showsin:
  9.         jmp short show
  10.                
  11.         table dw ag0,ag30,ag60,ag90,ag120,ag150,ag180        ;字符串偏移地址表
  12.         ag0      db '0',0                        ;sin(0)对应的字符串“0”
  13.         ag30     db '0.5',0                        ;sin(0)对应的字符串“0.5”
  14.         ag60     db '0.866',0                        ;sin(0)对应的字符串“0.866”
  15.         ag90     db '1',0                        ;sin(0)对应的字符串“1”
  16.         ag120    db '0.866',0                        ;sin(0)对应的字符串“0.866”
  17.         ag150    db '0.5',0                        ;sin(0)对应的字符串“0.5”
  18.         ag180    db '0',0                        ;sin(0)对应的字符串“0”
  19.                
  20. show:   push bx
  21.         push es
  22.         push si

  23.         mov bx,0b800h
  24.         mov es,bx

  25. ;以下用角度值/30 作为相对于table的偏移量,取得对应的字符串的偏移地址,放在bx中
  26.         mov ah,0
  27.         mov bl,30
  28.         div bl
  29.         mov bl,al
  30.         mov bh,0
  31.         add bx,bx
  32.         mov bx,table[bx]

  33. ;以下显示sin(x)对应的字符串
  34.         mov si,160*12+40*2
  35. shows:  
  36.                 mov ah,cs:[bx]
  37.         cmp ah,0
  38.         je showret
  39.         mov es:[si],ah
  40.         inc bx
  41.         add si,2
  42.         jmp shows

  43. showret:
  44.         pop si
  45.         pop es
  46.         pop bx
  47.         ret

  48. code ends

  49. end start
复制代码



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

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

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

  10. setscreen: jmp short set

  11.     table  dw sub1,sub2,sub3,sub4

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

  21. sret:       
  22.         pop bx       
  23.         iret

  24. ;功能子程序1:清屏
  25. sub1:   
  26.         push bx
  27.         push cx
  28.     push es
  29.         mov bx,0b800h
  30.         mov es,bx
  31.         mov bx,0
  32.         mov cx,2000
  33.        
  34. sub1s:  
  35.         mov byte ptr es:[bx],' '
  36.     add bx,2
  37.     loop sub1s
  38.     pop es
  39.     pop cx
  40.     pop bx
  41.         ret ;sub1 ends

  42. ;功能子程序2:设置前景色
  43. sub2:       
  44.         push bx
  45.         push cx
  46.         push es
  47.         mov bx,0b800h
  48.         mov es,bx
  49.         mov bx,1
  50.         mov cx,2000
  51.        
  52. sub2s:       
  53.         and byte ptr es:[bx],11111000b       
  54.         or es:[bx],al
  55.         add bx,2
  56.         loop sub2s

  57.         pop es
  58.         pop cx
  59.         pop bx
  60.         ret ;sub2 ends

  61. ;功能子程序3:设置背景色
  62. sub3:       
  63.         push bx
  64.         push cx
  65.         push es
  66.         mov cl,4
  67.         shl al,cl
  68.         mov bx,0b800h
  69.         mov es,bx
  70.         mov bx,1
  71.         mov cx,2000
  72.        
  73. sub3s:       
  74.         and byte ptr es:[bx],10001111b
  75.         or es:[bx],al
  76.         add bx,2
  77.         loop sub2s

  78.         pop es
  79.         pop cx
  80.         pop bx
  81.         ret ; sub3 ends

  82. ;功能子程序4:向上滚动一行
  83. sub4:       
  84.         push cx
  85.         push si
  86.         push di
  87.         push es
  88.         push ds

  89.         mov si,0b800h
  90.         mov es,si
  91.         mov ds,si
  92.         mov si,160                        ;ds:si指向第n+1行
  93.         mov di,0                        ;es:di指向第n行
  94.         cld
  95.         mov cx,24;共复制24行

  96. sub4s:       
  97.         push cx
  98.         mov cx,160
  99.         rep movsb                         ;复制
  100.           pop cx
  101.         loop sub4s

  102.         mov cx,80       
  103.         mov si,0
  104.        
  105. sub4s1:
  106.         mov byte ptr es:[160*24+si],' '                ;最后一行清空
  107.         add si,2
  108.         loop sub4s1

  109.         pop ds
  110.         pop es
  111.         pop di
  112.         pop si
  113.         pop cx
  114.         ret ;sub4 ends
复制代码


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

评分

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

查看全部评分

本帖被以下淘专辑推荐:

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-4-16 17:06

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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