Assembly 程序集中的标签如何知道其运行时地址?

Assembly 程序集中的标签如何知道其运行时地址?,assembly,operating-system,x86,nasm,z80,Assembly,Operating System,X86,Nasm,Z80,我正在学习汇编(z80和x86),现在开始掌握如何使用汇编程序构建二进制文件 如何使用带有绝对(相对于相对)地址的标签 据我所知,汇编程序会在编译时将标签转换为内存地址,但汇编程序如何知道标签在运行时驻留在哪个地址 对于z80裸机系统来说,这似乎足够简单,因为您可以将程序加载到特定的内存地址,并发送一个将程序计数器指向0000h的RST信号当操作系统运行时会发生什么情况 在操作系统中执行的代码是否不知道其起始地址(因此无法在标签上使用非相对操作码,如call和ret)如果机器代码不是位置独立的,

我正在学习汇编(z80和x86),现在开始掌握如何使用汇编程序构建二进制文件

如何使用带有绝对(相对于相对)地址的标签

据我所知,汇编程序会在编译时将标签转换为内存地址,但汇编程序如何知道标签在运行时驻留在哪个地址

对于z80裸机系统来说,这似乎足够简单,因为您可以将程序加载到特定的内存地址,并发送一个将程序计数器指向
0000h
RST
信号当操作系统运行时会发生什么情况


在操作系统中执行的代码是否不知道其起始地址(因此无法在标签上使用非相对操作码,如
call
ret

如果机器代码不是位置独立的,则有两种常见策略:

  • 在可执行文件中包含其他信息(也称为重新定位信息),这些信息将告诉操作系统需要调整的绝对地址的位置

  • 只需将可执行文件加载到它想要的地方,这意味着您可能需要首先逐出另一个可执行文件,或者需要为每个可执行文件提供单独的地址空间,因此首先就不需要争夺正确的位置


  • 汇编程序使用偏移量

    LABEL
         . . . . . 
    
         JMP LABEL // Knows the number of bytes to label. SO label can be anywhere.
    

    我想,你的程序将短于64 kb。在这种情况下,程序只需知道标签的偏移量(称为近跳转)。操作系统每次都以相同的偏移量启动程序,但以另一段启动。条件跳转和“jmp short”仅使用jmp命令和标签之间的差异。在某些特殊情况下,例如,如果一个过程在执行之前被存储到堆栈中,编译器会插入一段代码来更改jmp命令的参数。

    可能值得一读CP/M的解决方案,这很简单:二进制文件总是在一个固定地址加载,操作系统入口点总是在另一个固定地址。这在8位机器上是相当典型的,即使是那些有正式OSs的机器,也会被带入MS-DOS。多任务操作系统使用MMU在技术上也是可行的,因为每个进程都有自己的地址空间,所以每个二进制文件都可以认为是在同一个地方加载的

    中间的生成使用可重定位代码。要么它是位置独立的,因为CPU很容易支持它(根据经典的Mac OS和68000相对于PC寻址),要么,实际上,经典的双过程汇编程序的第二个过程在加载二进制文件时发生。因此,二进制代码是用占位符来编译的,占位符用于所有绝对地址,以及占位符所在位置的列表,以便在知道实际地址后可以替换这些占位符


    唯一的问题是它阻止了快速的虚拟内存。使用非MMU Mac OS方法,程序被编译为16kb的块,每个块内的跳转直接发生,远程跳转通过寻呼机。如果加载了目标块,则将其关闭;如果未加载,则加载该块,然后发生跳转。如果每次加载都需要计算和填写地址,则这种按需加载是禁止的。

    您研究过“可重新定位链接”吗?这些材料非常深入,我很乐意提供我所能提供的帮助您理解相关概念的微弱尝试,但如果您以前没有研究过这些内容,我不想说一些可能会在您头上飞扬的流行语。只要问问,我很乐意帮忙。顺便问一下,您使用的是16位汇编吗?e、 例如,您是否坚持使用当前研究的
    Ax、Bx、Cx、Dx、Si、Di
    等寄存器?
    call
    是相对的,可能您指的是像
    mov Ax、[symbol]
    这样的绝对寻址模式,而不是在运行时;并非所有标签都是相对的。一个简单的反例:
    ld bc,$some_string。。一些字符串:db'Hello',0
    。这里,需要在运行时知道
    某些\u字符串的绝对地址。在运行时没有标签。