1

我正在阅读有关英特尔 8086 架构的信息,但无法弄清楚以下有关分段的内容:我知道段寄存器分别指向段并包含 64kb 长段的基地址。但是谁计算以及在哪一点设置段寄存器中的物理地址?另外,因为一个物理地址可以被多个段访问:偏移量对和段可以重叠,你怎么能确定你不会覆盖一些东西?我可以在哪里阅读更多相关信息?

4

1 回答 1

3

一般来说,汇编器只会使用偏移地址来访问逻辑地址。例如看这段代码:

start   lea si,[hello]          ; Load effective address of string
        mov word [ds:si+10],0   ; Zero-terminate string after 10th letter
        jmp $                    ; Loop endlessly

; Fill rest of the segment with 0s
times 65536-($-$$) db 0x00

hello   db "I'm just outside of the current segment. Hello!",0

汇编器将尝试计算 'hello' 与程序原点的偏移量。由于没有定义原点,因此将假定为 0x0。但是,在这种情况下,'hello' 的偏移量将是 0x10000,它不适合 16 位。因此,汇编器会将地址截断为 0x0000。它不会改变任何段寄存器。但是,它可能会发出警告,例如test.asm:1: warning: word data exceeds bounds. 运行该程序时实际发生的情况是,该jmp $行被零覆盖,因为 hello 的地址被环绕,CPU 只会开始执行零,这不是您打算做的。

当然,只有在代码段和数据段相同的情况下。现在谁保证是这样?真的没人。特别是因为我仍然不知道您正在为哪个平台编码。使用正确的值设置段寄存器完全是您的责任。最简单的方法是:

push cs   ; Push address of code segment to stack
pop ds    ; Pop address back into data segment
push cs   ; Same for extra data segment
pop es    ;

这样您就可以确定您正在访问正确数据段中的偏移量。

现在关于“你如何确保代码段不与数据段重叠”,为什么不呢?当您的程序的数据小于 64KB 时,如果您的代码和数据段相同,那么它实际上是访问数据的最简单方法。

你怎么能确定你不会覆盖任何重要的东西?汇编程序无法帮助您,您必须检查自己是否要写入的段:偏移地址已经包含数据。

于 2015-04-22T18:36:50.207 回答