汇编器如何计算符号地址的段和偏移量? [英] How does assembler compute segment and offset for symbol addresses?

查看:0
本文介绍了汇编器如何计算符号地址的段和偏移量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

如何计算@DATA或LIKE 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,其值由操作系统的程序加载程序选择。(并且该值在组装时是未知的。)

这篇关于汇编器如何计算符号地址的段和偏移量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆