如何使用汇编得出一个位在内存中特定位置的结论?

How does one come to the conclusion that a bit is at a specific location in memory using assembly?

因此,我正在使用我在网上找到的 PDF 构建一个迷你 OS。到目前为止,我在该项目上取得了不错的进展,但是 pdf 已经达到了一个它并没有真正解释清楚的概念。

reader 给出了四个将字符串存储在寄存器中以进行打印的示例。 第四个例子是事情变得混乱的地方。使用下面的图 3.6,我们发现该字符串距位 '1e' 处的偏移量 30 个字节。

现在,我明白了为什么我们在 0x7cXX 处,因为它是引导扇区的偏移量。我不明白的是我们如何知道它的最后 2 位是 1e。

我认为答案是:嗯,我们将偏移量 0x0e 存储到 ah 寄存器,对吗? 而中断命令是0x10,也就是ah的低位。问题是,这并不能真正解释为什么对图 3.6 中的程序的二进制版本进行如此彻底的更改,我是从直觉而不是任何显着逻辑中得到的。

为什么我们知道字符串变量在 0x7c1e?

mov ah , 0x0e ; int 10/ ah = 0eh -> scrolling teletype BIOS routine

mov al , [0x7c1e ]
int 0 x10 ; Does this print an X?
jmp $ ; Jump forever.

the_secret :
db "X "

; Padding and magic BIOS number.
times 510 -( $ - $$ ) db 0
dw 0 xaa55

图3.6

```00 7 c 8a 07 cd 10 a0 1e 7c cd 10 e9 fd ff 58 00
```00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
```*
```00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa

正如评论中所建议的那样,使用标签是正确的方法。您还必须告诉汇编程序您的原点 (org) 是什么,以便它发出正确的地址。此外,您应该初始化数据段(ds)寄存器,因为您的内存负载会隐式使用它。

我假设您使用的是 NASM,因为 times 指令是一种 NASM 主义。要修复您的代码并让它像您应该的那样使用标签:

org 7C00h

xor ax, ax ; set ax to zero (well-known zeroing idiom)
mov ds, ax ; set ds base to zero
mov ah, 0x0E ; int 10/ ah = 0eh -> scrolling teletype BIOS routine
mov al, byte [the_secret]
int 0x10 ; This prints an 'X'
jmp $ ; Jump forever.

the_secret:
db "X "

; Padding and magic BIOS number.
times 510 - ($ - $$) db 0
dw 0xAA55

将其汇编为 NASM 的完整源代码会导致从地址 7C0Dh 处的字节加载。回到您的问题:我们如何知道最后两个半字节(8 位,2 个十六进制数字)是任何特定值?

我们可以计算前面的指令的大小,在这种情况下,6 条指令中的每一条都是 2 个字节,除了加载到 al 的 3 个字节。即 2 * 5 + 3 = 13 = 0Dh。但是,只要更改前面的代码,您就必须重新计算地址。

这正是我们使用汇编程序完成的任务,而不是仅仅为所有内容输入数值。要输入的数字将是用于指令的机器代码字节和用于引用的相对或绝对地址。使用助记符指令可以让汇编程序确定要发出的机器代码。使用标签可以让汇编程序将引用计算为数字地址。

只有非常有限的汇编程序不允许符号引用。如果您发现自己使用 86-DOS 调试器之一,它可能会限制您使用显式数字地址。但是你不应该将它们用于重要的组装。

总而言之,使用标签让汇编器完成它的工作。