gpt4 book ai didi

assembly - 汇编程序如何计算符号地址的段和偏移量?

转载 作者:行者123 更新时间:2023-12-05 01:00:13 24 4
gpt4 key购买 nike

我已经学习了编译器和汇编语言,所以我想编写自己的汇编程序作为练习。但我有一些问题;

如何计算@DATA 或 OFFSET/ADDR VarA 等段的地址?

以一个简单的汇编程序为例:

    .model small
.stack 1024
.data
msg db 128 dup('A')
.code
start:
mov ax,@data
mov ax,ds
mov dx, offset msg
; DS:DX points at msg
mov ah,4ch
int 21h ; exit program without using msg
end

那么汇编器是如何计算 @data的段地址的?部分?

以及它如何知道要为 mov dx, offset msg 立即放入什么内容?

最佳答案

汇编程序不知道在哪里 @datamsg最终会出现在内存中,因此会在对象 (.OBJ) 文件中生成称为重定位(或“修复”)的元数据,允许链接器和操作系统填充正确的值。

让我们看一下稍微不同的示例程序会发生什么:

.model small
.stack 1024
.data
msg db 'Hello, World!,'$'
.code
start:
mov ax,SEG msg
mov ds,ax
mov dx,OFFSET msg
mov ah,09h
int 21h ; write string in DS:DX to stdout
mov ah,4ch
int 21h ; exit(AL)
end start

汇编此文件时,汇编器无法知道链接器会将示例程序定义的任何内容放在哪里。这对您来说可能很明显,但汇编程序不能假设它看到了一个完整的程序。汇编器不知道您是否会将它与其他可能导致链接器放置 msg 的目标文件或库链接。除了数据段的开头之外的其他地方。

因此,当这个示例程序被汇编成一个目标文件时,汇编器会生成两个重定位记录。如果您使用 MASM 组装文件,您可以在使用/Fl 开关生成的列表文件中看到:
 ; listing of the .obj assembler output, before linking
0000 start:
0000 B8 ---- R mov ax,SEG msg
0003 8E D8 mov ds,ax
0005 BA 0000 R mov dx,OFFSET msg
0008 B4 09 mov ah,09h
R列表的机器代码列中的操作数旁边表示它们有重定位引用它们。当链接器从目标文件创建 MS-DOS 格式的可执行文件时,它将能够为 msg 提供从数据段开始的正确偏移量。 .该值是链接时间常数,因此只有 .obj ,而不是 .exe ,需要为它搬迁。

但是,链接器将无法提供 msg 段的位置。 (数据段),因为链接器不知道 MS-DOS 将在哪里加载可执行文件到内存中。 (在现代主流操作系统下,每个进程都有自己的虚拟地址空间,实模式只有一个地址空间,程序必须与设备驱动程序和 TSR 以及操作系统本身共享。)

因此,链接器将在生成的可执行文件中放置一个重定位,告诉 MS-DOS 根据加载位置调整立即操作数。

请注意,您可能希望通过编写一个仅适用于完整程序并仅生成 .COM 可执行文件的程序来简化您的汇编程序编写练习。这样就不用担心搬家了。您的汇编程序将决定在 .COM 格式允许的单个段中放置所有内容的位置。请注意,因为 .COM 文件不支持段重定位,指令如 mov ax,@datamov ax,SEG msg不能使用。相反,CS=DS=ES=SS 在程序启动时使用操作系统的程序加载器选择的值。 (并且在组装时不知道该值。)

关于assembly - 汇编程序如何计算符号地址的段和偏移量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29749979/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com