zoukankan      html  css  js  c++  java
  • 汇编学习笔记(13)直接定址表

    不加冒号的数据标号

    直接定址表顾名思义就是可以通过给定的数据直接找到所需的地址,主要通过数据标号来实现。

    到现在为止我们学习的数据标号的写法都是形如

    a: db 1,2,3

    其实还有一种写法是这样

    a db 1,2,3

    看上去只是少了个冒号,但是表示的含义可是大不相同。第一种写法a表示内存单元的地址,而第二种写法a不仅表示内存单元的地址,还表示了内存单元的长度。

     1 ;将a中的数据相加,结果存储在b中
     2 assume cs:code
     3 
     4 code segment
     5     
     6     a: db 1,2,3
     7     b: dw 0
     8     
     9 start:  mov si,offset a
    10         mov bx,offset b
    11         mov cx,3
    12 s:
    13         mov al,cs:[si]
    14         mov ah,0
    15         add cs:[bx],ax
    16         inc si
    17         loop s
    18     
    19         mov ax,4c00h
    20         int 21h
    21 code ends
    22 end start

    可以看到,结果已经存储在b中,采用不加冒号的数据标号写法可以使程序更加简洁。

     1 ;将a中的数据相加,结果存储在b中
     2 assume cs:code
     3 
     4 code segment
     5     
     6     a db 1,2,3
     7     b dw 0
     8     
     9 start:  mov si,0
    10         mov cx,3
    11 s:
    12         mov al,a[si]
    13         mov ah,0
    14         add b,ax
    15         inc si
    16         loop s
    17     
    18         mov ax,4c00h
    19         int 21h
    20 code ends
    21 end start

    因为不加冒号的数据标号还代表了内存单元的长度,所以"mov al,a[si]"就相当于"mov al,cs:[0]si","add b,ax"就相当于"add cs:[3]".

    任何事物都有其两面性,世上没有完全完美的东西,不加冒号的写法有一点是需要注意的:当把数据写在数据段时,必须用assume伪指令将数据段与某一个段寄存器联系起来,否则编译的时候会报错。还是刚才例子如果我们这么写

     1 ;将a中的数据相加,结果存储在b中
     2 assume cs:code
     3 
     4 data segment
     5     a db 1,2,3
     6     b dw 0
     7 data ends
     8 
     9 code segment
    10     
    11 start:  mov si,0
    12         mov cx,3
    13 s:
    14         mov al,a[si]
    15         mov ah,0
    16         add b,ax
    17         inc si
    18         loop s
    19     
    20         mov ax,4c00h
    21         int 21h
    22 code ends
    23 end start

    没错,can't address with segment register,错误信息已经很明显,定位不到段地址,这是为什么呢?上文已经说过,形如

    mov al,a[si]

    的指令在编译时是编译成怎样子的指令

    mov al,cs:0[si]

    我们把数据写在代码段中用的段地址是cs,而现在数据是写在数据段中,编译器在编译时就不知道数据段所对应的段寄存是多少了,所以需要用assume指令进行关联。

     1 ;将a中的数据相加,结果存储在b中
     2 assume cs:code,es:data
     3 
     4 data segment
     5     a db 1,2,3
     6     b dw 0
     7 data ends
     8 
     9 code segment
    10     
    11 start:  mov ax,data
    12         mov es,ax
    13         mov si,0
    14         mov cx,3
    15 s:
    16         mov al,a[si]
    17         mov ah,0
    18         add b,ax
    19         inc si
    20         loop s
    21     
    22         mov ax,4c00h
    23         int 21h
    24 code ends
    25 end start

    直接定址表

    我们通过一个例子来学习

     1 ;以十六进制的形式在屏幕上显示给定的字节型数据
     2 
     3 assume cs:code
     4 
     5 code segment
     6 
     7 start:
     8         mov al,'100'
     9         call show
    10         
    11         mov ax,4c00h
    12         int 21h
    13 
    14 show:
    15     jmp short show1
    16     table db '0123456789ABCDEF'
    17     
    18 show1:
    19     push es
    20     push bx
    21     mov ah,al
    22     shr ah,1
    23     shr ah,1
    24     shr ah,1
    25     shr ah,1    ;右移4位得到高位地址
    26     and al,00001111b
    27     
    28     mov bl,ah
    29     mov bh,0
    30     mov ah,table[bx];高4位的值作为偏移地址得到十六进制的值
    31     
    32     mov bx,0b800h
    33     mov es,bx
    34     mov es:[160*12+40*2],ah
    35     
    36     mov bl,al
    37     mov bh,0
    38     mov al,table[bx]
    39     mov es:[160*12+40*2],al
    40     
    41     pop bx
    42     pop es
    43     ret
    44 
    45 code ends
    46 end start

    在这个例子中,我们使用字节型数据的高4位和低4位来查找作为十六进制数据的偏移值,从而可以快速的找到对应的十六进制,这种直接的映射方法就叫做直接定址表。

  • 相关阅读:
    和远哥一起了解Hadoop的MapReduce是如何运行的
    远哥跟你说 Spring的 classpath 通配符加载配置文件
    远哥Amoeba源码分析之:核心类说明
    远哥推荐:面向网络的数据库 Neo4j
    Hadoop 1.0.3 在CentOS 6.2上安装过程 [个人安装通过的全程记录]
    OpenShift 添加 URL Rewrite 重写支持
    Access中空值处理
    解决EOS启动“不能连接到Server”的问题
    [原创]用递归写的一个object 转换成JSON的函数
    JSON反序列的问题原因查找
  • 原文地址:https://www.cnblogs.com/michaelle/p/4023329.html
Copyright © 2011-2022 走看看