zoukankan      html  css  js  c++  java
  • 直接定址表01 零基础入门学习汇编语言72

    第十六章:直接定址表01

     

    让编程改变世界

    Change the world by program


     

    描述了单元长度的标号

      这一章,我们讨论如何有效合理地组织数据,以及相关的编程技术。 本章中,我们要用到这种标号,先进行如下介绍。   前面的课程中,我们一直在代码段中使用标号来标记指令、数据、段的起始地址。 比如:下面的程序将code 段中的a 标号处的8个数据累加,结果存储到b标号处的字中。 [codesyntax lang="asm"]
    assume cs:code
    code segment
        a : db 1,2,3,4,5,6,7,8
        b : dw 0
    
    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
        mov ax,4c00h
        int 21h
    
    code ends
    end start
    [/codesyntax]   程序中,code、a、b、start、s都是标号。这些标号仅仅表示了内存单元的地址。 但是,我们还可以使用一种标号,这种标号不但表示内存单元的地址,还表示了内存单元的长度,即表示在此标号处的单元,是一个字节单元,还是字单元,还是双字单元。   上面的程序我们还可以写成这样:-->> [codesyntax lang="asm"]
    assume cs:code
    code segment
        a db 1,2,3,4,5,6,7,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
    [/codesyntax]   我们在code 段中使用的标号a、b后面没有“:” ,因此它们是可以同时描述内存地址和单元长度的标号。 标号a,描述了地址code:0,和从这个地址开始,以后的内存单元都是字节单元; 而标号b描述了地址code:8,和从这个地址开始,以后的内存单元都是字单元。   因为这种标号包含了对单元长度的描述,所以,在指令中,它可以代表一个段中的内存单元。 比如,对于程序中的b dw 0。 指令:mov ax,b 相当于:mov ax,cs:[8] 指令:mov b,2 相当于:mov word ptr cs:[8],2 指令:inc b 相当于:inc word ptr cs:[8]   在这些指令中,标号b 代表了一个内存单元,地址为code:8 ,长度为2 字节。 下面的指令会引起编译错误:mov al,b   为什么?     没错啦,聪明的你肯定意识到了:因为b代表的内存单元是字单元,而al 是8 位寄存器。 因此,如果我们将程序中的指令:add b,ax ,写为add b,al,将出现同样的编译错误。   对于程序中的a db 1,2,3,4,5,6,7,8 则有--->>> 指令: mov al,a [si] 相当于:mov al,cs:0[si]   指令: mov al,a[3] 相当于:mov al,cs:0[3]   指令: mov al,a[bx+si+3] 相当于:mov al,cs:0[bx+si+3]   可见,使用这种包含单元长度的标号, 可以使我们以简洁的形式访问内存中的数据。 以后,我们将这种标号称为数据标号。 它标记了存储数据的单元的地址和长度。 它不同于仅仅表示地址的地址标号。  

    检测点16.1

     

    在其他段中使用数据标号

      一般来说,我们不会在代码段中定义数据,而是将数据定义到其他段中。 在其他段中,我们也可以使用数据标号来描述存储数据的单元的地址和长度。   注意:在后面加有“:”的地址标号,只能在代码段中使用,不能在其他段中使用。 下边程序将data 段中 a标号处的 8 个数据累加,结果存储到 b标号处的字中。 [codesyntax lang="asm"]
    assume cs:code,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
    s:  mov al,a[si]
        mov ah,0
        add b,ax
        inc si
        loop s
        mov ax,4c00h
        int 21h
    
    code ends
    end start
    [/codesyntax]   注意,如果想在代码段中,直接用数据标号访问数据,则需要用伪指令assume 将标号所在的段和一个段寄存器联系起来。否则编译器在编译的时候,无法确定标号的段地址在哪一个寄存器中。   当然,这种联系是编译器需要的,但绝对不是说,我们因为编译器的工作需要,用 assume 指令将段寄存器和某个段相联系,段寄存器中就会真的存放该段的地址。   比如:在上面的程序中,我们要在代码段code中用 data段中的数据标号 a、b 访问数据,则必须用 assume 将一个寄存器和data 段相联。    

    在程序中,我们用 ds寄存器和 data 段相联,则编译器对相关指令的编译如下:

      指令: mov al,a[si] 编译为:mov al,[si+0]   指令: add b,ax 编译为:add [8],ax   因为这些实际编译出的指令,都默认所访问单元的段地址在ds中,而实际要访问的段为data,所以,若要访问正确,在这些指令执行前,ds 中必须为 data 段的段地址。   则,我们在程序中使用指令: mov ax,data mov ds,ax 设置ds指向data段。   我们可以将标号当作数据来定义,此时,编译器将标号所表示的地址当作数据的值。 比如: data segment

    a db 1,2,3,4,5,6,7,8

    b dw 0

    c dw a,b

    data ends 数据标号c处存储的两个字型数据为标号a、b 的偏移地址。 相当于: 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   数据标号c处存储的两个双字型数据为标号a的偏移地址和段地址、标号b 的偏移地址和段地址。 相当于: 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 seg操作符,功能为取得某一标号的段地址。 [buy] 获得所有教学视频、课件、源代码等资源打包 [/buy] [Downlink href='http://kuai.xunlei.com/d/LEINNXYXECCI']视频下载[/Downlink]
  • 相关阅读:
    EZchip花1.3亿美元买Tilera然后以8亿美元把自己与Tilera一起卖掉
    [OFC]Mellanox发布首个200Gb/s硅光子设备
    Mellanox 8亿美元收购EZchip
    EZchip将推全球首款100核64位ARM A-53芯片
    MyBatis映射文件5
    MyBatis映射文件4(参数获取#{}和${}/select标签详解[返回类型为list])
    MyBatis源码分析1 参数映射分析
    MyBatis映射文件3(参数处理Map)
    MyBatis映射文件2(不支持自增的数据库解决方案/参数处理[单参、多参、命名参数])
    MyBatis映射文件1(增删改、insert获取自增主键值)
  • 原文地址:https://www.cnblogs.com/LoveFishC/p/3847080.html
Copyright © 2011-2022 走看看