【发布时间】:2017-06-26 08:22:40
【问题描述】:
我正在尝试为 x86 编写一个简单的引导加载程序,但在理解 NASM 在组装程序时如何将标签转换为偏移量时遇到了问题。
(这只是一个演示程序)
bits 16
org 0x7C00
start:
mov ax, 0x07C0
mov ds, ax
mov si, msg
call print
hlt
print:
; print char array stored in [ds:si]
ret
msg db 'hello!'
我使用nasm -f bin 命令组装了代码。但它没有按预期工作。我在二进制输出上使用objdump -b binary -m i8086 -M intel -D,发现mov si, msg和call print对应的行被翻译成:
mov si,0x7c0d
call 0xc
所以当 NASM 用偏移值替换 mov si, msg 中的 msg 时,它使用相对于 0x0000 的绝对偏移量,但是当它转换 call print 中的 print 到偏移量时,它使用相对于 cs 的偏移量这是0x07C0。因此,当我尝试打印字符 [ds:si] 时,它并没有指向预期的位置。问题是为什么?如果我做错了,那么正确的方法是什么?
【问题讨论】:
-
call在机器码中具有相对 imm16 偏移量+0x0001,因此它正指向hlt之后,并且可以正常工作。顺便说一句,使用远jmp 0000:7C00 + <start_offset>启动引导加载程序代码是一个好习惯,以确保cs:ip对此“标准化”,因为某些 BIOS 会以不同的变化启动引导加载程序,例如07C0:0000,因此所有绝对偏移量和这样的 BIOS 通过cs寻址将是错误的。