【问题标题】:Understanding of boot loader assembly code and memory locations了解引导加载程序汇编代码和内存位置
【发布时间】:2018-09-01 10:19:15
【问题描述】:

我想检查一下我对以下引导加载程序代码的理解:

BITS 16

start:
    mov ax, 07C0h   ; Set up 4K stack space after this bootloader
    add ax, 288     ; (4096 + 512) / 16 bytes per paragraph
    mov ss, ax
    mov sp, 4096

    mov ax, 07C0h       ; Set data segment to where we're loaded
    mov ds, ax

    mov si, text_string ; Put string position into SI
    call print_string   ; Call our string-printing routine

    jmp $           ; Jump here - infinite loop!

    text_string db 'This is my cool new OS!', 0

print_string:           ; Routine: output string in SI to screen
    mov ah, 0Eh     ; int 10h 'print char' function

.repeat:
    lodsb           ; Get character from string
    cmp al, 0
    je .done        ; If char is zero, end of string
    int 10h         ; Otherwise, print it
    jmp .repeat

.done:
ret

    times 510-($-$$) db 0   ; Pad remainder of boot sector with 0s
    dw 0xAA55       ; The standard PC boot signature

以下是我对代码的理解:

移动斧头,07C0h:

  • 内存地址可以从栈段值(存储在ss寄存器中)和偏移量(存储在sp寄存器中)中获得。您可以通过执行以下操作获取地址:堆栈段值 x 16 + 偏移值。
  • 我们正在使用段 07C0h 在我们的代码中设置空间。所以当 07C0h 偏移 0 时,它将引用到 0x7C00 的地址。 BIOS 尝试从 0x7C00 引导代码。在 0x7C00 中复制的代码示例是 MBR。
  • 每个段以 16 字节为单位递增,因此 07C0h 将为您提供地址范围 0x7C00-0x7C0F。下一段 07C1h 将为您提供地址 0x7C10-0x7C1F。

加斧头,288

  • 要在引导加载程序之后设置 4K 堆栈空间,我们需要添加从 (4096 + 512)/16 字节获得的 288 每段。十进制值 288 等于 120h。
  • 现在存储在 ax 寄存器中的值是 08e0h,我通过以下方式获得:07c0h + 120h = 08e0h(120h 是十进制的 288)。

mov ss, ax

  • 将寄存器 ax 中的值复制到 ss 寄存器中。偏移量现在包含段:08e0h。

mov sp, 4096

  • 偏移值为 4096,即 0x1000h。 ss:sp 对的值为 08e0:1000。
  • 栈底从内存地址 0x8e00 开始,栈顶在 0x9e00(从 0x8e00 + 0x1000 = 0x9e00)。

这是内存中的代码和分配的空间的图表,如下所示。

注意:此图中的引导加载程序和内存引用很可能不正确,我假设它不会是连续的,并且汇编器将以不同的方式编译机器代码。但是,代码的开头将从较低的内存地址 (0x7C00) 开始,引导签名将从较高的地址开始(0xaa55 磁盘签名从 0x7c0:0x1fe 开始(物理地址 0x7c0*16 + 0x1fe=0x7dfe),它们是第一个 512 字节扇区的最后两个字节,从 0x7c0:0x0000 运行到 0x7c0:0x200(0x7C32 是 512 字节的结尾))。

奇怪的是,分配的空间是两个 4096 字节的块:一个用于堆栈,另一个包含代码和数据。我怀疑我在这里遗漏了一些东西。

【问题讨论】:

  • 0x7C0 放入 AX。 288(十进制)被添加到它。 288 十进制是 0x120。所以在添加 AX=0x8e0 之后。 0x8e0 放置在 SS(堆栈段)中。4096(0x1000)放置在 SP 中。因此堆栈指针为 SS:SP=0x8e0:0x1000 。即物理地址0x8e0*16+0x1000=0x9E00。堆栈从那里向下增长,但会在 0x8e0:0000 处回绕到 64kb 段的顶部。
  • 0xaa55 磁盘签名从 0x7c0:0x1fe(物理地址 0x7c0*16+0x1fe=0x7dfe)开始,这是从 0x7c0:0x0000 运行到 0x7c0:0x200 的第一个 512 字节扇区的最后两个字节
  • 谢谢。为了便于其他人在参考这篇文章时理解,我已经编辑了 Michael Petch 所做的更正。更正是 18h 到 120h(十进制 288)、07d8h 到 08e0h(7c0h + 120h)、256h 到 1000h(十进制 4096)、堆栈顶部在 0x9e00、堆栈包装在 0x8e00 和引导签名地址:0x7dfe。

标签: assembly x86-16 bootloader real-mode


【解决方案1】:

以下引导加载程序代码:

缺少如何设置汇编代码的相对地址的信息,即如何计算本地偏移量。通常,引导加载程序以org 0x7C00 开头,以明确代码期望从cs:ip = 0000:7C00 开始。但是你会这样做吗,ds=07C0 是错误的,这表明代码期望将偏移量组装为好像从07C0:0000 而不是0000:7C00 开始。虽然两个地址都针对相同的物理内存地址,但段:偏移量对是不同的。

每个段以 16 字节为单位递增,因此 07C0h 将为您提供地址范围 0x7C00-0x7C0F。下一段 07C1h 将为您提供地址 0x7C10-0x7C1F。

每个段为您提供 64kiB 范围,尽管起始地址仅增加 16 个字节,因此段之间有很多重叠,您可以通过多种组合寻址相同的物理地址。 IE。 ds=07C0 为您提供物理内存范围07C00-17BFF 的窗口。


那么您将值转换为十六进制是错误的(另请参见 Michael cmets)、288 = 0x120 和 4096 = 0x1000,但您正确地得出了 512B 引导加载程序代码(块设备的单个扇区)、4096B 空闲空间的结论,然后是 4096B 的堆栈空间。您是否会通过将超过 4096 个字节推入堆栈来填满堆栈,它不会在代码之后到达空闲空间,而是会回绕到 08E0:FFFE(远高于堆栈的原始开头)。

我假设它不会是顺序的,并且汇编器会以不同的方式编译机器代码。

恰恰相反,源代码中的指令和定义的字节在生成的机器代码中按顺序发出。使用“listing”命令行开关来查看汇编器如何为特定行发出机器代码。例如,您是否会在BITS 16 指令之后的开头移动text_string db 'This is my cool new OS!', 0 行,然后该文本将位于机器代码的开头,由BIOS 在/从0000:7C00 地址加载和执行,将文本字节作为指令执行.

【讨论】:

  • 此代码基于MikeOS's original bootloader,它们不使用org 指令,因此默认为org 0x0000。他们的引导加载程序实际上是为使用 0x7c0 段而设计的。
  • 通常将自己从物理地址 0x7c00 重新定位到较低内存(即:0x600)的引导加载程序将使用 0x7c0 作为初始段和 0x0000 的偏移量。 org 0x0000 可以轻松地重新定位到任何段。
  • 我发现了 Michael 的一篇关于 ORG 指令使用的优秀帖子。它建议明确设置寄存器以确保代码在不同的硬件/虚拟仿真器上按预期工作。这是link。关于段范围,我没有注意20位地址和SS值的左移。所以范围是每段 64kib。感谢您指出。
  • @supmethods 64kiB(“b”通常用于“位”,而“B”通常用于字节......不是每个人都遵循它,所以你应该总是检查惯例/主题/what-makes-sense,但如果您从事汇编工作,则必须了解这两者。(如果您将阅读较旧的书籍/文本,则“kB”始终表示“kiB”,即“kibi” 2^ 10,不是“千” 10^3。如果无聊,请查看en.wikipedia.org/wiki/Binary_prefix了解详细信息...在IT时代的开始,没有必要区分它们,因为每个人都知道在IT环境中什么是有意义的,但是磁盘供应商用了 10^3 把它毁了
猜你喜欢
  • 1970-01-01
  • 2019-11-18
  • 2013-06-04
  • 1970-01-01
  • 1970-01-01
  • 2021-09-03
  • 2017-12-20
  • 1970-01-01
  • 2011-01-08
相关资源
最近更新 更多