在nasm中标记偏移量

时间:2017-06-26 08:22:41

标签: assembly x86 nasm x86-16

我正在尝试为x86编写一个简单的bootloader,我在理解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, msgcall print对应的行被翻译为:

mov    si,0x7c0d
call   0xc

所以当NASM用msg替换mov si, msg中的0x0000时,它会使用相对于print的绝对偏移量,但是当它将call print转换为cs时offset它使用相对于0x07C0的偏移量[ds:si]。因此,当我尝试打印字符{{1}}时,未指向预期的位置。问题是为什么?如果我做错了,这样做的正确方法是什么?

1 个答案:

答案 0 :(得分:3)

这是反汇编程序的人工制品:它将相对位移转换为绝对地址。
如果您将0x7c00作为原点传递它将显示正确的值。

for (int j = 0; j < 9; j++) 
{
    outcome = 1;

    for (int i = 0; i < 9; i++) 
        outcome *= list[i];

    outcome = outcome / list[j];
    Console.WriteLine(outcome);
}

ndisasm例子

错误是你使用0x7c0作为c:\>ndisasm -b 16 -o 7c00h a 00007C00 B8C007 mov ax,0x7c0 00007C03 8ED8 mov ds,ax 00007C05 BE0D7C mov si,0x7c0d 00007C08 E80100 call word 0x7c0c 00007C0B F4 hlt 00007C0C C3 ret ,这个值是代码的来源,如ds所示,是零而不是0x7c00。

例如,ds位于原点,NASM为0x7c00,start汇编为mov si, start
在运行时mov si, 0x7c00位于线性地址 0x07c00,但由于start已初始化的方式,指针[ds:si]指向0x07c0:0x7c00 = 0x0f800。

您可以使用零初始化dsds将指向0x0000:0x7c00 = 0x07c00)或将原点设置为零([ds:si]将指向0x07c0:0x0000 = 0x07c00) 。

作为旁注:您可以使用[ds:si]和其他细分受众群的不同值做得很好,但这是您必须记住的事项,并且在您移动代码或设置ISR 但是,您必须初始化所有段寄存器,包括cs 如果这是您第一次尝试使用引导加载程序,我建议ss:spcs相同。
无论如何,如果你想尝试不同的值,NASM支持ds输出格式的Multi-sections,这是它支持的最接近分割的东西。