了解引导加载程序程序集代码和内存位置 [英] Understanding of boot loader assembly code and memory locations

查看:117
本文介绍了了解引导加载程序程序集代码和内存位置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I want to check my understanding of the following bootloader code:

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:

mov ax, 07C0h:

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

    add ax, 288

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

      mov ss, ax

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

        mov sp, 4096

        • 偏移量值为4096,即0x1000h. ss:sp对的值为08e0:1000.
        • 堆栈的底部从内存地址0x8e00开始,堆栈的顶部从0x9e00(从0x8e00 + 0x1000 = 0x9e00)开始.
        • 下面是内存中的代码和分配的空间的图表,如下所示.

          Here's a diagram of the code in memory and the space allocated as below.

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

          Note: the bootloader and the memory reference in this diagram are most likely incorrect, I am assuming that it won't be sequential and the assembler will compile the machine code differently. However, the start of the code will be starting at the lower memory address (0x7C00) and the boot signature will start at the higher address (0xaa55 disk signature starts at 0x7c0:0x1fe (physical address 0x7c0*16 + 0x1fe=0x7dfe) which are the last two bytes of the first 512 byte sector which runs from 0x7c0:0x0000 to 0x7c0:0x200(0x7C32 which is the end of the 512 bytes)).

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

          It strange to see space allocated are two blocks of 4096 bytes though: one for the stack and the other contains the code and data. I suspect I am missing something here.

          推荐答案

          以下是引导加载程序代码:

          following bootloader code:

          缺少有关如何设置汇编代码的相对地址的信息,即如何计算局部偏移量.通常,引导加载程序以org 0x7C00开头,以明确表明希望在cs:ip = 0000:7C00处启动的代码.但是您会这样做吗,ds=07C0将会是错误的,那就是该代码建议代码期望偏移量像从07C0:0000而不是0000:7C00开始一样进行汇编.虽然两个地址都针对相同的物理内存地址,但是segment:offset对却不同.

          It's missing info how it will set up relative address of assembled code, i.e. how the local offsets will be calculated. Usually bootloaders start with org 0x7C00 to make it explicit the code expects to be started at cs:ip = 0000:7C00. But would you do that, the ds=07C0 would be wrong, that one suggests the code expects the offsets be assembled as if it starts at 07C0:0000 instead of 0000:7C00. While both addresses target the identical physical memory address, the segment:offset pairs are different then.

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

          Each segment increments in blocks of 16 bytes, so 07C0h will give you address range 0x7C00-0x7C0F. The next segment 07C1h will give you address 0x7C10-0x7C1F.

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

          Each segment gives you 64kiB range, although the start address advances only by 16 bytes, so there's lot of overlap between segments and you can address the same physical address by many combinations. I.e. ds=07C0 gives you window into physical memory range 07C00-17BFF.

          然后,您将值转换为十六进制是错误的(另请参阅Michael注释),288 = 0x120,并且4096 = 0x1000,但是您正确地得出结论:512B的引导加载程序代码(块设备的单个扇区),4096B的备用空间,然后是4096B的堆栈空间.您是否希望通过向堆栈中推入4096个以上的字节来填充堆栈,所以它不会在代码执行后到达剩余空间,而是会缠绕到08E0:FFFE(远高于堆栈的原始开头).

          Then your conversions of values to hexadecimal are wrong (see also Michael comments), 288 = 0x120, and 4096 = 0x1000, but you correctly conclude there's 512B of bootloader code (single sector of block device), 4096B of spare space, and then 4096B of stack space. Would you fill up the stack by pushing more than 4096 bytes into it, it will not hit the spare space after code, but will wrap around to 08E0:FFFE (well above the original start of stack).

          我假设它不是顺序的,汇编器将以不同的方式编译机器代码.

          I am assuming that it won't be sequential and the assembler will compile the machine code differently.

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

          Quite opposite, instructions and defined bytes in the source code are emitted sequentially in the resulting machine code. Use the "listing" command line switch to see yourself how the assembler emits machine code for particular lines. Would you for example move the text_string db 'This is my cool new OS!', 0 line at the beginning after BITS 16 directive, that text would be then at the beginning of machine code, loaded and executed by BIOS at/from 0000:7C00 address, executing the text bytes as instructions.

          这篇关于了解引导加载程序程序集代码和内存位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆