代码之家  ›  专栏  ›  技术社区  ›  Pyjong

汇编程序中的寻址

  •  2
  • Pyjong  · 技术社区  · 15 年前

    有些东西我消化不了。我在学汇编程序,现在我在编地址这一章。我理解括号的解引用概念,但不知何故,当我看到它的用法时,我就是不能理解它的要点。更确切地说,我的困惑是从这里开始的:

    mov al, [L1]
    

    这里我假设l1是一个例子,它是一种宏,后来被机器代码中的实际地址所代替,对吧?

    所以这个指令的作用是:解引用 al 注册(因为您很难更改物理地址)并将值更改为存储在 L1 .

    如果到目前为止一切正常:

    mov [L1], al
    

    也就是说,一定有一个地址被存储了(所以这样做是有意义的),然后你把它改到内存中的其他地方,对吧?

    如果你能告诉我,如果你没有看到任何错误,请这样做,这将使我有可能继续学习。

    最后一件事,nasm增加了 0xAA55 在我的代码下(这个序列应该结束程序对吧?),为什么会有那么多次?

    3 回复  |  直到 6 年前
        1
  •  4
  •   Peter Cordes    6 年前

    L1 通常/可能 标签 , 与内存中的一个特定地址相关联。程序员为了方便而定义各种标签,这些标签被用来象征性地表示内存中的特定位置(l1是一个糟糕的名称;标签通常表示位置的潜在用途:比如pingcounter、errormessage、login等等)。

    一个1字节静态存储的标签是C编译器将如何实现 char L1; 在全球范围内。


    在NASM语法中, mov edi, L1 将集合到 mov eax, imm32 形式 mov ,即标签地址将在机器代码中变为32位立即数。(汇编器不知道最后的数值,但链接器知道。)注意在MASM语法中,这是一个加载,您需要 mov edi, OFFSET L1 获取标签地址作为即时消息。

    但是 mov al, [L1] 将汇编成另一条指令,机器代码中嵌入32位地址作为要取消引用的地址。此指令从地址l1加载1字节,并将其放在al中。

    在汇编语言中,这种间接寻址模式是用方括号括住给定指令的源操作数或目标操作数来表示的。(但不能同时使用:x86只支持每条指令最多一个显式内存操作数。)

    mov al, [L1]
    

    使用存储在l1中的地址来定位内存中的某个位置,并在该位置读取1字节(=8位=AL寄存器的大小),然后将其加载到AL寄存器中。

      mov [L1], al
    

    反过来做。即,具体地说,读取存储在l1中的地址,使用这个地址在存储器中找到一个特定的位置,并将al寄存器的内容存储在那里。


    如果您理解以下信息对于x86系列中较新的处理器来说是不完整和有些过时的,那么 primer on the 8086 architecture 对于开始使用x86系列的汇编语言可能非常有用。
    从这种“CPU的古老性”(实际上仍在使用)开始的好处是,基本概念都在那里,没有新的寄存器集、奇特的寻址模式、操作模式和其他概念的阻碍。较新CPU的更大尺寸、功能和模式只会带来选项的组合爆炸,全部(大多数?)在他们的方式上有用,但本质上与开始无关。

        2
  •  3
  •   Benoit Miller    15 年前

    很难理解你的问题,但我会尽力帮忙的。

    在程序集中,符号只是地址的名称。在汇编源代码中,l1是在别处定义的符号,汇编程序将其解析为内存偏移量。

    解引用时(使用[]符号),可以解引用寄存器(如“mov al,[esi]”)或地址(如“mov al,[l1]”)。这两个语句做同样的事情,唯一的区别是地址来自哪里。

    我建议下载 Intel CPU Documentation 并浏览指令参考。如果您不想不知所措,可以从一个较旧的x86处理器(比如486或更旧的处理器)开始阅读,该文档并不十分友好,但手头有它是非常有用的。

    我不知道NASM的具体内容,15年前我在TurboAssembler中学习过汇编,现在这些知识仍然很有用:)

    另外,我建议您尝试在google上搜索“x86程序集教程”,您会发现许多相关的文档可能对您有用。

        3
  •  1
  •   Earlz    15 年前

    还有最后一件事,nasm加了一个 一堆0xAA55在我的代码下面(这个 序列应该结束 程序正确吗?),为什么会这样 很多次?非常感谢你 读到这里..

    我很确定这只适用于创建引导加载程序的情况。这是“引导签名”。假设您将此代码写入软盘(您生成的机器代码是否也正好是512字节?),那么当你想用这个引导加载程序代码启动计算机时,bios会查看软盘并确定它是否是一个真正的引导加载程序。为此,它将查看软盘第一个扇区的最后两个字节,该扇区应该是 0xAA55 以指示它是可引导的。(同样,如果您从硬盘驱动器、拇指驱动器或其他驱动器启动,也可以使用相同的方法。CD略有不同,因为它们有4096字节的扇区)

    在你的源代码中,就像最后一行 $(times.. db 0xAA55 或者类似的?如果不打算创建引导加载程序,可以有效地删除该行。