我正在学习汇编(z80和x86),现在我正准备使用汇编程序构建二进制文件。
如何使用带有绝对(相对于相对)地址的标签?
根据我的理解,汇编程序会在编译时将标签转换为内存地址,但汇编程序如何知道标签在运行时将驻留在哪个地址?
对于z80裸机系统来说似乎很简单,因为您可以将程序加载到特定的内存地址并发送RST
信号,将程序计数器指向0000h
。 当操作系统正在运行时会发生什么??
在操作系统中执行的代码不会知道其起始地址(因此无法在标签上使用call
和ret
之类的非相对操作码吗?
答案 0 :(得分:3)
如果机器代码与位置无关,则有两种常见的策略:
在可执行文件中包含附加信息(AKA重定位信息),告知操作系统需要调整绝对地址的位置
只需将可执行文件加载到所需的位置,这意味着您可能需要首先逐出另一个,或者您需要为每个人提供单独的地址空间,因此不会在第一名
答案 1 :(得分:2)
可能值得阅读CP / M的解决方案,这很简单:二进制文件始终加载到固定地址,操作系统入口点始终位于另一个固定地址。这在8位机器上是相当典型的,即使是那些具有正式操作系统的机器,也是通过MS-DOS进行的。使用MMU的多任务操作系统在技术上也是可行的,因为每个进程都有自己的地址空间,因此每个二进制文件都可以认为它是在同一个地方加载的。
使用可重定位代码之间的生成。它的位置是独立的,因为CPU很容易支持(根据Classic Mac OS和68000的相对于PC的寻址),或者实际上,当加载二进制文件时,会发生经典的双遍汇编程序的第二次传递。因此,二进制文件是使用所有绝对地址的占位符编译的代码,以及这些占位符的位置列表,以便在知道实际地址后可以替换它们。
唯一的问题是它会阻止快速的虚拟内存。使用非MMU Mac OS方法,程序被编译为16kb块,每个块内的跳跃直接发生,远程跳转通过寻呼机。如果加载了目标块,则关闭它,如果没有则加载,然后发生跳转。如果需要计算地址并在每次加载时填写,则按需加载是非常容易的。
答案 2 :(得分:0)
我猜,你的程序将短于64 kb。在这种情况下,程序只需要知道标签的OFFSET(称为Near-Jump)。操作系统每次在同一个OFFSET启动程序,但在另一个段启动。 condintional jumps和" jmp short"仅使用jmp命令和标签之间的差异。在某些特殊情况下,例如,如果在执行之前将过程存储到堆栈中,则编译器会插入更改jmp命令参数的代码。
答案 3 :(得分:-1)
汇编程序使用抵消。
LABEL
. . . . .
JMP LABEL // Knows the number of bytes to label. SO label can be anywhere.