我正在阅读关于intel 8086的架构,并且无法弄清楚以下关于分段的事情:我知道段寄存器分别指向段并包含64kb长段的基址。但谁计算并在哪个点设置段寄存器中的物理地址?此外,因为一个物理地址可以被多个段访问:偏移对和段可以重叠,您如何确定不会覆盖某些内容?我可以在哪里阅读更多相关信息?
答案 0 :(得分: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
汇编程序将尝试计算'你好'的偏移量。从该计划的起源。由于没有定义原点,因此将假设为0x0。但是,你好'你好'在这种情况下,它将是0x10000,不适合16位。因此,Assembler会将地址截断为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时,如果您的代码和数据段相同,它实际上是访问数据的最简单方法。
你怎么能确定你没有覆盖任何重要的东西?汇编程序无法为您提供帮助,您必须检查自己正在写入的段:偏移地址是否已包含数据。