簡體   English   中英

GNU程序集引導加載程序將無法啟動

[英]GNU assembly boot loader won't boot

我一直在閱讀以下教程:

http://intermezzos.github.io/book/multiboot-headers.html

不幸的是,它使用NASM而不是GNU匯編程序,因為我通常使用GNU工具鏈而不是使用它。 本教程有以下簡單的hello world程序:

section .multiboot_header
header_start:
    dd 0xe85250d6                ; magic number
    dd 0                         ; protected mode code
    dd header_end - header_start ; header length

    ; checksum
    dd 0x100000000 - (0xe85250d6 + 0 + (header_end - header_start))

    ; required end tag
    dw 0    ; type
    dw 0    ; flags
    dd 8    ; size
header_end:

它提供了多引導頭以及以下內容:

global start
section .text
bits 32
start:
    mov word [0xb8000], 0x0248 ; H
    mov word [0xb8002], 0x0265 ; e
    mov word [0xb8004], 0x026c ; l
    mov word [0xb8006], 0x026c ; l
    mov word [0xb8008], 0x026f ; o
    mov word [0xb800a], 0x022c ; ,
    mov word [0xb800c], 0x0220 ;
    mov word [0xb800e], 0x0277 ; w
    mov word [0xb8010], 0x026f ; o
    mov word [0xb8012], 0x0272 ; r
    mov word [0xb8014], 0x026c ; l
    mov word [0xb8016], 0x0264 ; d
    mov word [0xb8018], 0x0221 ; !
    hlt

它們與以下的linker.ld文件鏈接在一起:

ENTRY(start)

SECTIONS {
    . = 1M;

    .boot :
    {
        /* ensure that the multiboot header is at the beginning */
        *(.multiboot_header)
    }

    .text :
    {
        *(.text)
    }
}

編譯和運行所有這些可以通過以下方式完成:

nasm -f elf64 boot_nasm.asm
nasm -f elf64 multiboot_header_nasm.asm
ld --nmagic --output=kernel.bin --script=linker.ld multiboot_header_nasm.o boot_nasm.o

檢查教程如何使用內核創建iso映像以及如何使用qemu啟動。 現在我已按如下方式移植源代碼以使用GNU匯編程序:

    .section .multiboot_header
header_start:
    .long 0xe85250d6             # magic number
    .long 0                      # protected mode code
    .long header_end - header_start

    # checksum
    .long 0x100000000 - (0xe85250d6 + 0 + (header_end - header_start))

    # required end tag
    .word 0 # type
    .word 0 # flags
    .long 8 # size
header_end:

    .text
    .global start
    .code32
start:
    movw $0x0248, (0xb8000)      # H
    movw $0x0265, (0xb8002)      # e
    movw $0x026c, (0xb8004)      # l
    movw $0x026c, (0xb8006)      # l
    movw $0x026f, (0xb8008)      # o
    movw $0x022c, (0xb800a)      # ,
    movw $0x0220, (0xb800c)      #
    movw $0x0277, (0xb800e)      # w
    movw $0x026f, (0xb8010)      # o
    movw $0x0272, (0xb8012)      # r
    movw $0x026c, (0xb8014)      # l
    movw $0x0264, (0xb8016)      # d
    movw $0x0221, (0xb8018)      # !
    hlt

我通過以下方式編譯和鏈接這些:

as boot.S -o boot.o
as multiboot_header.S -o multiboot_header.o
ld --nmagic --output=kernel.bin --script=linker.ld multiboot_header.o boot.o

objdump表明兩種情況下輸出的kernel.bin與每個段中的代碼相同。 唯一的區別是片段所在的偏移量略有不同。 主要區別在於nasm版本啟動GNU匯編版本沒有啟動

GNU匯編程序版本給出了error: no multiboot header found.

這是兩個創建的二進制文件的objdump輸出:

 % objdump -D -s kernel_nasm.bin 

kernel_nasm.bin:     file format elf64-x86-64

Contents of section .boot:
 100000 d65052e8 00000000 18000000 12afad17  .PR.............
 100010 00000000 08000000                    ........        
Contents of section .text:
 100020 66c70500 800b0048 0266c705 02800b00  f......H.f......
 100030 650266c7 0504800b 006c0266 c7050680  e.f......l.f....
 100040 0b006c02 66c70508 800b006f 0266c705  ..l.f......o.f..
 100050 0a800b00 2c0266c7 050c800b 00200266  ....,.f...... .f
 100060 c7050e80 0b007702 66c70510 800b006f  ......w.f......o
 100070 0266c705 12800b00 720266c7 0514800b  .f......r.f.....
 100080 006c0266 c7051680 0b006402 66c70518  .l.f......d.f...
 100090 800b0021 02f4                        ...!..          

Disassembly of section .boot:

0000000000100000 <header_start>:
  100000:   d6                      (bad)  
  100001:   50                      push   %rax
  100002:   52                      push   %rdx
  100003:   e8 00 00 00 00          callq  100008 <header_start+0x8>
  100008:   18 00                   sbb    %al,(%rax)
  10000a:   00 00                   add    %al,(%rax)
  10000c:   12 af ad 17 00 00       adc    0x17ad(%rdi),%ch
  100012:   00 00                   add    %al,(%rax)
  100014:   08 00                   or     %al,(%rax)
    ...

Disassembly of section .text:

0000000000100020 <start>:
  100020:   66 c7 05 00 80 0b 00    movw   $0x248,0xb8000(%rip)        # 1b8029 <start+0xb8009>
  100027:   48 02 
  100029:   66 c7 05 02 80 0b 00    movw   $0x265,0xb8002(%rip)        # 1b8034 <start+0xb8014>
  100030:   65 02 
  100032:   66 c7 05 04 80 0b 00    movw   $0x26c,0xb8004(%rip)        # 1b803f <start+0xb801f>
  100039:   6c 02 
  10003b:   66 c7 05 06 80 0b 00    movw   $0x26c,0xb8006(%rip)        # 1b804a <start+0xb802a>
  100042:   6c 02 
  100044:   66 c7 05 08 80 0b 00    movw   $0x26f,0xb8008(%rip)        # 1b8055 <start+0xb8035>
  10004b:   6f 02 
  10004d:   66 c7 05 0a 80 0b 00    movw   $0x22c,0xb800a(%rip)        # 1b8060 <start+0xb8040>
  100054:   2c 02 
  100056:   66 c7 05 0c 80 0b 00    movw   $0x220,0xb800c(%rip)        # 1b806b <start+0xb804b>
  10005d:   20 02 
  10005f:   66 c7 05 0e 80 0b 00    movw   $0x277,0xb800e(%rip)        # 1b8076 <start+0xb8056>
  100066:   77 02 
  100068:   66 c7 05 10 80 0b 00    movw   $0x26f,0xb8010(%rip)        # 1b8081 <start+0xb8061>
  10006f:   6f 02 
  100071:   66 c7 05 12 80 0b 00    movw   $0x272,0xb8012(%rip)        # 1b808c <start+0xb806c>
  100078:   72 02 
  10007a:   66 c7 05 14 80 0b 00    movw   $0x26c,0xb8014(%rip)        # 1b8097 <start+0xb8077>
  100081:   6c 02 
  100083:   66 c7 05 16 80 0b 00    movw   $0x264,0xb8016(%rip)        # 1b80a2 <start+0xb8082>
  10008a:   64 02 
  10008c:   66 c7 05 18 80 0b 00    movw   $0x221,0xb8018(%rip)        # 1b80ad <start+0xb808d>
  100093:   21 02 
  100095:   f4                      hlt    

這是使用GNU匯編程序創建的版本:

 % objdump -D -s kernel.bin     

kernel.bin:     file format elf64-x86-64

Contents of section .boot:
 100000 d65052e8 00000000 18000000 12afad17  .PR.............
 100010 00000000 08000000                    ........        
Contents of section .text:
 100000 66c70500 800b0048 0266c705 02800b00  f......H.f......
 100010 650266c7 0504800b 006c0266 c7050680  e.f......l.f....
 100020 0b006c02 66c70508 800b006f 0266c705  ..l.f......o.f..
 100030 0a800b00 2c0266c7 050c800b 00200266  ....,.f...... .f
 100040 c7050e80 0b007702 66c70510 800b006f  ......w.f......o
 100050 0266c705 12800b00 720266c7 0514800b  .f......r.f.....
 100060 006c0266 c7051680 0b006402 66c70518  .l.f......d.f...
 100070 800b0021 02f4                        ...!..          

Disassembly of section .boot:

0000000000100000 <header_start>:
  100000:   d6                      (bad)  
  100001:   50                      push   %rax
  100002:   52                      push   %rdx
  100003:   e8 00 00 00 00          callq  100008 <header_start+0x8>
  100008:   18 00                   sbb    %al,(%rax)
  10000a:   00 00                   add    %al,(%rax)
  10000c:   12 af ad 17 00 00       adc    0x17ad(%rdi),%ch
  100012:   00 00                   add    %al,(%rax)
  100014:   08 00                   or     %al,(%rax)
    ...

Disassembly of section .text:

0000000000100000 <start>:
  100000:   66 c7 05 00 80 0b 00    movw   $0x248,0xb8000(%rip)        # 1b8009 <header_end+0xb7ff1>
  100007:   48 02 
  100009:   66 c7 05 02 80 0b 00    movw   $0x265,0xb8002(%rip)        # 1b8014 <header_end+0xb7ffc>
  100010:   65 02 
  100012:   66 c7 05 04 80 0b 00    movw   $0x26c,0xb8004(%rip)        # 1b801f <header_end+0xb8007>
  100019:   6c 02 
  10001b:   66 c7 05 06 80 0b 00    movw   $0x26c,0xb8006(%rip)        # 1b802a <header_end+0xb8012>
  100022:   6c 02 
  100024:   66 c7 05 08 80 0b 00    movw   $0x26f,0xb8008(%rip)        # 1b8035 <header_end+0xb801d>
  10002b:   6f 02 
  10002d:   66 c7 05 0a 80 0b 00    movw   $0x22c,0xb800a(%rip)        # 1b8040 <header_end+0xb8028>
  100034:   2c 02 
  100036:   66 c7 05 0c 80 0b 00    movw   $0x220,0xb800c(%rip)        # 1b804b <header_end+0xb8033>
  10003d:   20 02 
  10003f:   66 c7 05 0e 80 0b 00    movw   $0x277,0xb800e(%rip)        # 1b8056 <header_end+0xb803e>
  100046:   77 02 
  100048:   66 c7 05 10 80 0b 00    movw   $0x26f,0xb8010(%rip)        # 1b8061 <header_end+0xb8049>
  10004f:   6f 02 
  100051:   66 c7 05 12 80 0b 00    movw   $0x272,0xb8012(%rip)        # 1b806c <header_end+0xb8054>
  100058:   72 02 
  10005a:   66 c7 05 14 80 0b 00    movw   $0x26c,0xb8014(%rip)        # 1b8077 <header_end+0xb805f>
  100061:   6c 02 
  100063:   66 c7 05 16 80 0b 00    movw   $0x264,0xb8016(%rip)        # 1b8082 <header_end+0xb806a>
  10006a:   64 02 
  10006c:   66 c7 05 18 80 0b 00    movw   $0x221,0xb8018(%rip)        # 1b808d <header_end+0xb8075>
  100073:   21 02 
  100075:   f4                      hlt    

現在我正在看它,看起來GNU匯編程序版本有一個重疊的.boot和.text段,所以在加載文件時grub可能會用.text部分的數據覆蓋.boot部分。 任何人都知道如何解決這個問題?

多引導規范說:

Multiboot標頭必須完全包含在OS映像的前8192字節內,並且必須是長字(32位)對齊。

objdump給了我們:

Idx Name              Size      File off  Algn
  3 .multiboot_header 00000018  00000040  2**0 CONTENTS, READONLY

注意Algn=2**0

解決方案:指定對齊:

.section .multiboot_header
.balign 4
header_start:

對於nasm版本也應該這樣做,由於文件布局,它只是意外地在那里工作。

除了Jester指出的對齊問題之外,我認為鏈接器腳本是可疑的。 它將兩個不同的輸入部分放入兩個不同的輸出部分,這可能不是您想要的,並在某種程度上解釋了您通過objdump看到的差異。 嘗試類似以下內容:

ENTRY(start)

SECTIONS {
    . = 1M;

    .text :
    {
        /* ensure that the multiboot header is at the beginning */
        *(.multiboot_header)
        *(.text)
    }
}

或者,強制gas使“.multiboot_header”成為multiboot_header.s中的可分配部分:

.section .multiboot_header, "a"

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM