我怎样才能JMP在我的MBR搬迁code? [英] How can I JMP to relocated code in my MBR?

查看:227
本文介绍了我怎样才能JMP在我的MBR搬迁code?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图写一个非常简单的MBR开始学习如何编写一个MBR /内核。这是我迄今为止(从其他的MBR片创建)。我使用NASM,然后LD链接获得二进制是只使用两个NASM有点不同,但是这似乎并不成为问题。

我第一次开始与 JMP 0:继续但似乎跳转到 0000:7c22 (或 001D 单独NASM ......我相信我没有指定它开始于 7c00 ),但即时寻找跳到:7a22 :7a1d ,被拆迁code的地址。我试着只用 JMP继续,然后根据下面看到取消注释,增加堆栈指针继续指针,推动它和RET。我得到的是,当dd'ed我的第一个部门一个闪烁的光标。任何帮助是AP preciated。

 ; NASM + LD NASM评论
全球_start
_开始:
    XOR CX,CX; 6631c9 31c9设置段寄存器为零
    MOV ES,CX; 8ec1 8ec1
    MOV DS,CX; 8ed9 8ed9
    MOV SS,CX; 8ed1 8ed1
    MOV SP,0x7A00; 66bc007a bc007a堆栈
    MOV DI,SP;搬迁点6689e7 89e7底部
    MOV ESI,_start; be007c0000 66be00000000
    CLD; FC FC
    MOV CH,1; B501 B501 CX = 256
    代表MOVSW; f366a5 F3A5自我复制到0:7A00;----------------------------------------------------------------------------------------------------------------------
    XOR EAX,EAX
    MOV AX,SP
    加斧,继续    ; JMP 0:继续; JMP附近ea227c00000000 ea1d000000自我复制
                            ;要么
    ; JMP继续; (eb00)
    推EAX
    RET
;----------------------------------------------------------------------------------------------------------------------继续:
    STI; FB FB错误:
    MOV ESI,ERRORMSG; be3b7c0000(be36)66be36000000错误消息禄
    MOV啊,0x0E的; b40e b40e
    MOV BX,7; 66bb bb0700
DISP:
    LODSB;交流交流
    CMP啊,0×00; 80fc00 80fc00
    JE结束; 7404 7404
    INT 10H; CD10 CD10
    JMP DISP; ebf6 ebf6结束:
    NOP; 90 90
    JMP结束; ebfd ebfd infinte循环ERRORMSG 10分贝,你搞砸了。',13,0次(0x1b8 - ($ - $$))NOP; 90 90填充UID分贝0xf5,0xbf,为0x0F,为0x18;唯一的磁盘IDBLANK次2​​分贝0PT1分贝0x80,0x20,0x21,0x00,0x0C,0x50,0x7F,0x01,0x00,0x08,0x00,0x00,0xb0,0x43,0xF9,0x0D;第一分区项
PT2次16分贝0;第二个分区条目
PT3次16分贝0;第三分区入口
PT4次16分贝0;四分区项BOOTSIG DW 0xAA55将;引导签名[/ code]

谢谢!


解决方案

当你发现你可以设置原点到 ORG 0x7A00 为您的整个引导程序。这工作得很好。在code那份引导扇区0x7A00不依赖于是绝对的,只是那些亲戚的任何标签。这个答案更是一个思想实验,并接近它的不同方式。

如果我们想要显示复制作为一个例子之前的字符串会发生什么?有哪些可能的选择?


  1. NASM 的允许BIN格式( -f斌),以有采取一个的虚拟起点(原点)和物理地址(开始)。这种方法的限制太大,引导程序是如何布局。

  2. 使用 LD 的链接脚本定义引导程序的布局。

  3. 重新code为使用的 ORG 的(原点)的0x0000,并设置相应的段寄存器。看到我的其他答案了这个问题。

这答案的重点选项2.如何解释的 LD 的链接描述文件的工作是为#1过宽。该 LD 的手动是最好的信息来源,它也有例子。我们的想法是,我们允许链接器脚本中进行布局引导程序。我们可以建立LMA(装载存储器地址)来指定部分将被加载到内存中的内存地址。该VMA是一款原点。一个区段内的所有标记和地址将相对于其VMA解决。

便利,我们可以使用一个部分与特定LMA到引导签名直接放置到输出文件中,而不是在组件code指定它。我们也可以用定义从可以从组装code被访问的链接脚本符号的 NASM 的extern 指令。

一个优势,这一切都是你可以在任何你想要的顺序确定在汇编code段和链接器脚本将重新排序的东西。您也可以将多个目标文件链接起来。包含你想先出现启动code目标文件中应首先列出。

该链接脚本的布局大致是这样的:


 来的0x7c00原点启动code(boot.text)相对的非重定位部分
引导数据的非重定位部分(boot.data)
---------------------------------------字对齐
启动code(rel.text)的重新定位的一部分 - 相对于0x7a00原点
引导数据重新定位的一部分(rel.data)
偏移0x1b8分区数据的重新定位的一部分(partition.data)
---------------------------------------
偏移0x1fe引导签名


一个链接脚本,将这种布局的引导加载程序可能看起来是这样的:

  ENTRY(_start);
OUTPUT(elf_i386);截面
{
    / *设置主引导程序偏移的基础* /
    _bootbase = 0x7c00; / *如果引导程序最初加载到内存中* /
    _relbase = 0x7a00; / *地址整个启动扇区将被复制到
                           这个链接脚本希望它是字对齐* /
    _partoffset = 0x1b8; / *偏移UID和分区数据*的/
    _sigoffset = 0x1fe; / *偏移引导签名字* /
    / * SUBALIGN(N)的输出部分将覆盖对齐
     *即encontered任何输入部分的* /    / *这是引导加载程序code,并且有望从0x7c00运行数据* /
    .bootinit _bootbase:SUBALIGN(2)
    {
        *(boot.text);
        *(boot.data);
    }    / *请注意,在分区表中引用的任何数据都将
     *只能从code,它是在.bootrel部分可用* /    / *分区的数据* /
    .partdata _relbase + _partoffset:
        AT(_bootbase + _partoffset)SUBALIGN(0)
    {
        *(partition.data);
    }    / *引导签名* /
    .bootsig:
        AT(_bootbase + _sigoffset)SUBALIGN(0)
    {
        SHORT(0xAA55将);
    }
    / *区域的长度,以16位字复制* /
    _rel_length = 256;
    / *地址复制到* /
    _rel_start = _relbase; / *字对齐的起始地址* /    / * code和数据会想到跑一次搬迁
     *放置在本节。与字边界。
     *本relocateable code和数据都将被置于右
     *在输出文件的.bootinit后段* /
    .bootrel _relbase + SIZEOF(.bootinit):
        AT(_bootbase + SIZEOF(.bootinit))SUBALIGN(2)
    {
        *(rel.text);
        *(rel.data);
    }
}

使用这个链接描述您的code的修订副本,并在其定义的符号可以是这样的:

 位16EXTERN _bootbase
EXTERN _relbase
EXTERN _rel_length
EXTERN _rel_start部分boot.text
                            ;评论
全球_start
_开始:
    XOR CX,CX;集段寄存器为零
    MOV ES,CX
    MOV DS,CX
    MOV SS,CX
    MOV SP,0x7A00;堆
    CLD.copymsg:
    MOV SI,copymsg;复制消息
    MOV啊,0x0E的; 0E TTY输出
    MOV BX,7;页码
.dispcopy:
    LODSB;加载下一个字符
    测试人,人;相较于零
    JZ .END;如果是这样,端
    INT 10H;显示字符
    JMP .dispcopy;循环
。结束:
    MOV DI,_rel_start;搬迁点开始
    MOV SI,_bootbase;原来的位置,从复制
    MOV CX,_rel_length; CX =字被复制
    代表MOVSW;自我复制到目的地    JMP 0:rel_entry;远JMP自我复制部分rel.text
rel_entry:
    STI;允许中断    MOV SI,successmsg;错误信息的位置
    MOV啊,0x0E的; 0E TTY输出
    MOV BX,7;页码
.disp:
    LODSB;加载下一个字符
    测试人,人;相较于零
    JE .END;如果是这样,端
    INT 10H;显示字符
    JMP .disp;循环    CLI;禁止中断
。结束:
    HLT; CPU HLT
    JMP .END; infinte循环部分rel.data
successmsg 10分贝,成功!,13,0部分boot.data
copymsg DB 10,副本之前!,13,0部分partition.data
UID分贝0xf5,0xbf,为0x0F,为0x18;唯一的磁盘IDBLANK次2​​分贝0PT1分贝0x80,0x20,0x21,0x00,0x0C,0x50,0x7F,为0x01
    DB 0x00,0x08,0x00,0x00,0xb0,0x43,0xF9,0x0D
PT2次16分贝0
PT3次16分贝0
PT4次16分贝0

作为一个实验,以确保在 boot.text 部分中的code可能会在 boot.data <访问数据/ code>我显示复制之前的字符串。然后我做了的 FAR JMP 应用于搬迁code。被拆迁code显示一条成功的字符串。

我修改了code不使用像32位寄存器的 ESI 的,因为你将在实模式下执行此code。我还修正你的无限循环使用 HLT 指令。

在code和链接脚本可以被修改为只从数据迁移到第512字节开始复制,但超出了这个答案的范围。


一看拆卸

这有0x7c00原点的 .bootinit 部分如下。这是一个的 objdump的的该节段(不为简洁的数据):

 部分.bootinit拆卸:00007c00&LT; _start计算值:
    7c00:31 C9 XOR CX,CX
    7c02:8E C1 MOV ES,CX
    7c04:8E D9 MOV DS,CX
    7c06:8E D1 MOV SS,CX
    7c08:公元前00 7A MOV SP,0x7a00
    7c0b:FC CLD00007c0c&所述; _start.copymsg计算值:
    7c0c:是2E 7C MOV SI,0x7c2e
    7c0f:B4 0E MOV啊,0xe
    7C11:BB 07 00 MOV BX,为0x700007c14&所述; _start.dispcopy计算值:
    7c14:AC的LOD人,BYTE PTR DS:[SI]
    7C15:84 C0的测试人,人
    7c17:74 04 JE 7c1d&LT; _start.end&GT;
    7c19:CD 10 INT为0x10
    7c1b:EB F7 JMP 7c14&LT; _start.dispcopy&GT;00007c1d&所述; _start.end计算值:
    7c1d:BF 00 7A MOV DI,0x7a00
    7c20:是00 7C MOV SI,0x7c00
    7c23:B9 00 01 MOV CX,为0x100
    7c26:F3 A5代表MOVS WORD PTR ES:[二],WORD PTR DS:[SI]
    7c28:EA 3E 7A 00 00 JMP为0x0:0x7a3e

在左侧列中的所有地址VMA出现相对原点0x7c00正确设置。在 FAR JUMP 的( JMP为0x0:0x7a3e )也跃升到这里的一切搬迁的位置(复制)。在 .bootrel 部分的类似的缩写转储显示为:

 部分.bootrel拆卸:00007a3d&LT; rel_entry,为0x1计算值:
        ...00007a3e&所述; rel_entry计算值:
    7a3e:FB STI
    7a3f:是54 7A MOV SI,0x7a54
    7a42:B4 0E MOV啊,0xe
    7a44:BB 07 00 MOV BX,为0x700007a47&所述; rel_entry.disp计算值:
    7a47:AC的LOD人,BYTE PTR DS:[SI]
    7a48:3C 00 CMP人,为0x0
    7a4a:74 05 JE 7a51&LT; rel_entry.end&GT;
    7a4c:CD 10 INT为0x10
    7a4e:EB F7 JMP 7a47&LT; rel_entry.disp&GT;
    7a50:FA CLI00007a51&所述; rel_entry.end计算值:
    7a51:F4 HLT
    7A52:EB FD JMP 7a51&LT; rel_entry.end&GT;

的VMA在左侧列是相对于0x7A00开头这是正确的。指令 MOV SI,0x7a54 是一个绝对接近的内存地址,这是正确的连接coded到引用 successmsg 地址(Ⅰ剪断了出于简洁的数据,因此不会出现)。

中的条目:

  00007a3d&LT; rel_entry,为0x1计算值:
        ...

都与 .bootrel 部分调整到一个更字边界信息。有了这个链接脚本 rel_entry 将永远有一个偶地址。


编译和链接这个引导程序

最简单的方法是使用以下命令:

  NASM -f ELF32 -o boot.o boot.asm
LD -melf_i386 -Tlinker.ld -o BOOT.BIN --oformat =二进制boot.o

应该指出的是,我们正在使用的 ELF32 的用的 NASM 的格式,而不是的 BIN 的。的 LD 的则用于创建二进制文件 BOOT.BIN 这应该是引导扇区的512字节的图像。 linker.ld 是链接的脚本文件的名称。

如果你想要的是能够得到一个对象转储,那么你可以使用这些命令来组装和连接方便:

  NASM -f ELF32 -o boot.o boot.asm
LD -melf_i386 -Tlinker.ld -o boot.elf boot.o
objcopy把-O二进制boot.elf BOOT.BIN

从第一个方法不同的是,我们不使用 - oformat =二进制 LD 的选项。其结果将是,一个的 ELF32 的图像将被生成并放置在输出文件 boot.elf 。我们不能用 boot.elf 直接作为我们的引导映像,所以我们使用的 objcopy把的到的 ELF32 的文件转换名为二进制文件 BOOT.BIN 。做这种方式的用处可如果我们用这样的命令来转储的内容和拆卸可见的 ELF 的文件:

  objdump的boot.elf -Mintel -mi8086 -Dx


  • -D 选项拆卸所有

  • -x 输出头

  • -mi8086 拆解为16位8086 code

  • -Mintel 拆装应的 INTEL 的语法,而不是默认的 ATT 的语法

I'm trying to write an extremely simple MBR to start learning how to write an MBR/Kernel. This is what I have so far (created from pieces of other MBRs). The binary I get from using nasm and then ld to link is a bit different from just using nasm for both, but that doesn't appear to be the problem.

I first started with jmp 0:continue but that appears to jump to 0000:7c22 (or 001d with nasm alone... i believe i didnt specify that it starts at 7c00) but im looking to jump to :7a22 or :7a1d, the address of the relocated code. I tried using just jmp continue and then as seen uncommented below, adding the stack pointer to the continue pointer, pushing it and ret. All I get is a blinking cursor when dd'ed to my 1st sector. Any help is appreciated.

                            ; nasm+ld       nasm            comment
global _start
_start:
    xor    cx, cx           ; 6631c9        31c9            Set segment registers to zero
    mov    es, cx           ; 8ec1          8ec1
    mov    ds, cx           ; 8ed9          8ed9
    mov    ss, cx           ; 8ed1          8ed1
    mov    sp, 0x7A00       ; 66bc007a      bc007a          Stack
    mov    di, sp           ; 6689e7        89e7            Bottom of relocation point
    mov    esi, _start      ; be007c0000    66be00000000
    cld                     ; fc            fc
    mov    ch, 1            ; b501          b501            cx = 256
    rep movsw               ; f366a5        f3a5            Copy self to 0:7A00

;----------------------------------------------------------------------------------------------------------------------
    xor    eax,eax
    mov    ax, sp
    add    ax, continue

    ;jmp    0:continue      ; ea227c00000000    ea1d000000      near JMP to copy of self
                            ; or
    ;jmp    continue        ; (eb00)
    push eax
    ret
;----------------------------------------------------------------------------------------------------------------------

continue:
    sti                     ; fb            fb

ERROR:
    mov esi, errormsg       ; be3b7c0000 (be36) 66be36000000        Error Message loc
    mov ah, 0x0E            ; b40e          b40e
    mov bx, 7               ; 66bb          bb0700
disp:
    lodsb                   ; ac            ac
    cmp ah, 0x00            ; 80fc00        80fc00
    je end                  ; 7404          7404
    int 10h                 ; cd10          cd10
    jmp disp                ; ebf6          ebf6

end:
    nop                     ; 90            90
    jmp end                 ; ebfd          ebfd            infinte loop

errormsg db 10,'YOU MESSED UP.',13,0

times (0x1b8 - ($-$$)) nop  ; 90            90          Padding

UID db 0xf5,0xbf,0x0f,0x18                                         ;Unique Disk ID

BLANK times 2 db 0

PT1 db 0x80,0x20,0x21,0x00,0x0C,0x50,0x7F,0x01,0x00,0x08,0x00,0x00,0xb0,0x43,0xF9,0x0D ;First Partition Entry
PT2 times 16 db 0                                      ;Second Partition Entry
PT3 times 16 db 0                                      ;Third Partition Entry
PT4 times 16 db 0                                      ;Fourth Partition Entry

BOOTSIG dw 0xAA55                                      ;Boot Signature[/code]

Thanks!

解决方案

As you have discovered you can set the origin point to ORG 0x7A00 for your entire bootloader. That works perfectly well. The code that copies the boot sector to 0x7A00 doesn't rely on any labels that are absolute, just relatives ones. This answer is more of a thought experiment and a different way of approaching it.

What would happen if we wanted to display a string before the copy as an example? What are some possible options?

  1. NASM allows for the BIN format (-f bin) to have sections that take on a virtual starting point (origin point) and a physical address (start). This method is too restrictive for how a bootloader is laid out.
  2. Use an LD linker script to define the layout of the bootloader.
  3. Reorganize code to use an ORG (origin point) of 0x0000 and set the segment registers accordingly. See my other answer to this question.

This answer focuses on option 2. Explaining how LD Linker scripts work is too broad for Stackoverflow. The LD manual is the best source of information, and it does have examples. The idea is that we allow the bootloader to be laid out inside the linker script. We can set up LMA (Load Memory Address) to specify the memory address where the section will be loaded into memory. The VMA is the origin point for a section. All labels and addresses within a section will be resolved relative to its VMA.

Conveniently we can use a section with a specific LMA to place the boot signature directly into the output file, rather than specify it in the assembly code. We can also define symbols from the linker script that can be accessed from the assembly code using the NASM extern directive.

One advantage to all this is that you can define sections in your assembly code in any order you want and the linker script will reorder things. You can also link together multiple object files. The object file containing the boot code you want to appear first should be listed first.

The layout of this linker script roughly looks like this:

Non-relocatable portion of boot code (boot.text) Relative to an origin of 0x7c00
Non-relocatable portion of boot data (boot.data)
--------------------------------------- Word aligned
Relocatable portion of boot code (rel.text) - Relative to an origin of 0x7a00
Relocatable portion of boot data (rel.data)
Relocatable portion of partition data at offset 0x1b8 (partition.data)
---------------------------------------
Boot signature at offset 0x1fe

A linker script that would layout this boot loader could look something like:

ENTRY(_start);
OUTPUT(elf_i386);

SECTIONS
{
    /* Set the base of the main bootloader offsets */
    _bootbase = 0x7c00; /* Where bootloader initially is loaded in memory */
    _relbase  = 0x7a00; /* Address entire bootsector will be copied to
                           This linker script expects it to be word aligned */
    _partoffset = 0x1b8; /* Offset of UID and Partition data */
    _sigoffset  = 0x1fe; /* Offset of the boot signature word */


    /* SUBALIGN(n) in an output section will override the alignment
     * of any input section that is encontered */

    /* This is the boot loader code and data that is expected to run from 0x7c00 */
    .bootinit _bootbase : SUBALIGN(2)
    {
        *(boot.text);
        *(boot.data);
    }

    /* Note that referencing any data in the partition table will
     * only be usable from the code that is in the .bootrel section */

    /* Partition data */
    .partdata _relbase + _partoffset :
        AT(_bootbase + _partoffset) SUBALIGN(0)
    {
        *(partition.data);
    }

    /* Boot signature */
    .bootsig :
        AT(_bootbase + _sigoffset) SUBALIGN(0)
    {
        SHORT(0xaa55);
    }
    /* Length of region to copy in 16-bit words */
    _rel_length = 256;
    /* Address to copy to */
    _rel_start = _relbase; /* Word aligned start address */

    /* Code and data that will expect to run once relocated
     * is placed in this section. Aligned to word boundary.
     * This relocateable code and data will be placed right
     * after the .bootinit section in the output file */
    .bootrel _relbase + SIZEOF(.bootinit) :
        AT(_bootbase + SIZEOF(.bootinit)) SUBALIGN(2)
    {
        *(rel.text);
        *(rel.data);
    }
}

A revised copy of your code using this linker script and the symbols defined in it could look like:

BITS 16

extern _bootbase
extern _relbase
extern _rel_length
extern _rel_start

section boot.text
                            ; comment
global _start
_start:
    xor    cx, cx           ; Set segment registers to zero
    mov    es, cx
    mov    ds, cx
    mov    ss, cx
    mov    sp, 0x7A00       ; Stack
    cld

.copymsg:
    mov si, copymsg         ; Copy message
    mov ah, 0x0E            ; 0E TTY Output
    mov bx, 7               ; Page number
.dispcopy:
    lodsb                   ; Load next char
    test al, al             ; Compare to zero
    jz .end                 ; If so, end
    int 10h                 ; Display char
    jmp .dispcopy           ; Loop
.end:
    mov    di, _rel_start   ; Beginning of relocation point
    mov    si, _bootbase    ; Original location to copy from
    mov    cx, _rel_length  ; CX = words to copy
    rep movsw               ; Copy self to destination

    jmp    0:rel_entry      ; far JMP to copy of self

section rel.text
rel_entry:
    sti                     ; Enable interrupts

    mov si, successmsg      ; Error Message location
    mov ah, 0x0E            ; 0E TTY Output
    mov bx, 7               ; Page number
.disp:
    lodsb                   ; Load next char
    test al, al             ; Compare to zero
    je .end                 ; If so, end
    int 10h                 ; Display char
    jmp .disp               ; Loop

    cli                     ; Disable interrupts
.end:
    hlt                     ; CPU hlt
    jmp .end                ; infinte loop

section rel.data
successmsg db 10,'Success!',13,0

section boot.data
copymsg db 10,'Before copy!',13,0

section partition.data
UID db 0xf5,0xbf,0x0f,0x18  ;Unique Disk ID

BLANK times 2 db 0

PT1 db 0x80,0x20,0x21,0x00,0x0C,0x50,0x7F,0x01
    db 0x00,0x08,0x00,0x00,0xb0,0x43,0xF9,0x0D
PT2 times 16 db 0
PT3 times 16 db 0
PT4 times 16 db 0

As an experiment to make sure that the code in the boot.text section could access the data in the boot.data I display a string before the copy. I then do a FAR JMP to the relocated code. The relocated code displays a success string.

I modified the code to not use the 32-bit registers like ESI since you will be executing this code in real mode. I also amended your infinite loop to use the HLT instruction.

The code and linker script could be modified to only copy from the start of the relocated data up to the 512th byte, but is beyond the scope of this answer.


A Look at the Disassembly

The .bootinit section that has an origin point of 0x7c00 is provided below. This is an OBJDUMP snippet of that section (without the data for brevity):

Disassembly of section .bootinit:

00007c00 <_start>:
    7c00:       31 c9                   xor    cx,cx
    7c02:       8e c1                   mov    es,cx
    7c04:       8e d9                   mov    ds,cx
    7c06:       8e d1                   mov    ss,cx
    7c08:       bc 00 7a                mov    sp,0x7a00
    7c0b:       fc                      cld

00007c0c <_start.copymsg>:
    7c0c:       be 2e 7c                mov    si,0x7c2e
    7c0f:       b4 0e                   mov    ah,0xe
    7c11:       bb 07 00                mov    bx,0x7

00007c14 <_start.dispcopy>:
    7c14:       ac                      lods   al,BYTE PTR ds:[si]
    7c15:       84 c0                   test   al,al
    7c17:       74 04                   je     7c1d <_start.end>
    7c19:       cd 10                   int    0x10
    7c1b:       eb f7                   jmp    7c14 <_start.dispcopy>

00007c1d <_start.end>:
    7c1d:       bf 00 7a                mov    di,0x7a00
    7c20:       be 00 7c                mov    si,0x7c00
    7c23:       b9 00 01                mov    cx,0x100
    7c26:       f3 a5                   rep movs WORD PTR es:[di],WORD PTR ds:[si]
    7c28:       ea 3e 7a 00 00          jmp    0x0:0x7a3e

All the VMA addresses on the left column appear to be properly set relative to the origin point 0x7c00. The FAR JUMP (jmp 0x0:0x7a3e) also jumped to the location where everything was relocated (copied). A similar abbreviated dump of the .bootrel section appears as:

Disassembly of section .bootrel:

00007a3d <rel_entry-0x1>:
        ...

00007a3e <rel_entry>:
    7a3e:       fb                      sti
    7a3f:       be 54 7a                mov    si,0x7a54
    7a42:       b4 0e                   mov    ah,0xe
    7a44:       bb 07 00                mov    bx,0x7

00007a47 <rel_entry.disp>:
    7a47:       ac                      lods   al,BYTE PTR ds:[si]
    7a48:       3c 00                   cmp    al,0x0
    7a4a:       74 05                   je     7a51 <rel_entry.end>
    7a4c:       cd 10                   int    0x10
    7a4e:       eb f7                   jmp    7a47 <rel_entry.disp>
    7a50:       fa                      cli

00007a51 <rel_entry.end>:
    7a51:       f4                      hlt
    7a52:       eb fd                   jmp    7a51 <rel_entry.end>

The VMA in the left column is relative to the beginning of 0x7A00 which is correct. The instruction mov si,0x7a54 is an absolute near memory address and it is properly encoded to reference the successmsg address (I snipped the data out for brevity so it doesn't appear).

The entries:

00007a3d <rel_entry-0x1>:
        ...

Are information related to aligning the .bootrel section to an even word boundary. With this linker script rel_entry will always have an even address.


Compiling and Linking this Bootloader

The easiest way is to use these commands:

nasm -f elf32 -o boot.o boot.asm
ld -melf_i386 -Tlinker.ld -o boot.bin --oformat=binary boot.o

It should be pointed out that we are using ELF32 format with NASM, not BIN. LD is then used to create the binary file boot.bin which should be a 512 byte image of the boot sector. linker.ld is the name of the linker script file.

If you want the convenience of being able to get an object dump then you can use these commands to assemble and link:

nasm -f elf32 -o boot.o boot.asm
ld -melf_i386 -Tlinker.ld -o boot.elf boot.o
objcopy -O binary boot.elf boot.bin

The difference from the first method is that we don't use --oformat=binary option with LD. The result will be that an ELF32 image will be generated and placed in the output file boot.elf. We can't use boot.elf directly as our boot image, so we use OBJCOPY to convert the ELF32 file to a binary file called boot.bin. The usefulness of doing it this way can be seen if we use a command like this to dump the contents and disassembly of the ELF file:

objdump boot.elf -Mintel -mi8086 -Dx

  • -D option is disassemble all
  • -x output the headers
  • -mi8086 disassemble as 16-bit 8086 code
  • -Mintel disassembly should be INTEL syntax rather than default ATT syntax

这篇关于我怎样才能JMP在我的MBR搬迁code?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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