2016-06-23 7 views
3
나는 다음과 같은 튜토리얼을 통과했습니다

가 부팅되지 않습니다 오히려 그것을 대신 사용하십시오.GNU 조립 부트 로더는

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 파일과 함께 연결되어 있습니다 : 멀티 부트 헤더뿐만 아니라 다음과 같은 기능을 제공

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: 

:

자습서는 다음과 같은 사소한 안녕하세요 세계 프로그램을 가지고

: 컴파일이 모두 실행 는
ENTRY(start) 

SECTIONS { 
    . = 1M; 

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

    .text : 
    { 
     *(.text) 
    } 
} 

하여 수행 할 수 있습니다210

자습서를 확인하여 커널로 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 어셈블러 버전은이 아닙니다. 이제

% 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 어셈블러를 사용하여 만든 버전을 여기

% 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 어셈블러 버전은 여기 나에게 error: no multiboot header found.

을 제공하는이 만든 바이너리에서 objdump를 출력입니다 GNU Assembler 버전이 .boot 및 .text 세그먼트가 겹쳐져있는 것처럼 보입니다. 그래서 파일을로드하는 동안 아마 ov가됩니다. .text 섹션의 데이터로 .boot 섹션을 erwrit합니다. 누구든지이 문제를 해결하는 방법을 알고 있습니까?

+0

희망 부트 로더가 당신을 알려줍니다

ENTRY(start) SECTIONS { . = 1M; .text : { /* ensure that the multiboot header is at the beginning */ *(.multiboot_header) *(.text) } } 

는 다른 방법으로, 힘 gas이 multiboot_header.s에 할당 가능한 섹션 ".multiboot_header"할 커널처럼. 또는 어쩌면 그것은 그것을 좋아하고, 그것은 시동을 부르고 문제는 어디에서든지 당신이 부호가 얼마나에 도착하는지보기 위하여 디버거를 이용한다. 또한 사용하는 부트 로더를 지정하십시오. – Jester

+0

"유일한 차이점은 세그먼트가있는 오프셋이 약간 다릅니다"입니다. 이것이 유일한 차이점이라면 GAS 버전이 부팅되지 않는 이유는 근본적이어야합니다. 그 차이점은 정확히 무엇입니까? – davmac

+0

grub.cfg 파일에 대한 자습서와 qemu에 의해 부팅 된 iso 이미지가 생성되는 방법을 확인하십시오. 내가받은 오류 메시지로 내 질문을 업데이트했습니다. 이 특별한 오류 메시지는 grub에서 비롯된 것이므로 두 경우 모두 BIOS를 지나치게됩니다. – del

답변

2

멀티 부트 사양 말한다 :

멀티 부트 헤더는 OS 이미지의 제 8192 바이트 내에 완전히 포함되어야하고, 정렬 (32 비트) LONGWORD되어야한다.

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 버전 수행해야합니다 그것으로 인해 파일 레이아웃이 작동 단지 사고입니다.

+0

알아두면 좋습니다. 내가이 스펙을 파고 들기 전에 잠시 시간이 걸렸을 것입니다. 원본에이 문제를 지적했을만한 것이 없었기 때문입니다. 감사! – del

+0

@del로 문제가 완전히 해결 되었습니까? 나는 그것이 조금이라도 놀랐을 것이다. 아래 내 대답을 참조하십시오. – davmac

+0

이제 작동합니다. 그러나 linker.ld 파일을 변경하면 섹션 오프셋이 겹치지 않으므로 이제 오프셋이 NASM 버전의 끝으로 일치합니다. – del

1

Jester에서 지적한 정렬 문제 외에도 링커 스크립트가 용의성이 있다고 생각합니다. 그것은 두 개의 다른 입력 섹션을 두 개의 다른 출력 섹션에 넣습니다. 원하는 출력 섹션이 아니며 을 통해 표시되는 차이점을 어느 정도 설명합니다. 대신 다음과 같은 시도 : 그것은 '아무튼 왜

.section .multiboot_header, "a" 
+1

두 섹션인지 여부는 중요하지 않으며 할당 가능할 필요도 없습니다. 지옥, 섹션 일 필요는 없습니다. 단지 파일에 있어야하고 제대로 정렬되어야합니다. – Jester

+0

@Jester 일 수도 있지만, Nasm 버전을 사용하면 분명히로드 할 수 있습니다. 실제 멀티 부트 사양의 예제 코드도 마찬가지입니다. OP가 튜토리얼을 따르고 있기 때문에 튜토리얼의 나머지 부분에서이를 요구할 수 있습니다. 두 섹션을 하나의 출력 섹션으로 묶으면 최종 레이아웃이 무엇인지 분명하게 알 수 있습니다. – davmac

+0

@davmac : 그러나 (어떤 코드와 블로그가 있는지에 관계없이) 멀티 부팅 스펙을 읽으면 처음 8k 바이트에 나타나고 4 바이트가 정렬되어야한다는 것을 분명하게 알 수 있습니다. 그 의미에서 레이아웃, 섹션 및 속성은 의미가 없습니다. GRUB은 파일을 열고 첫 번째 8k의 어디에 있는지 또는 어떻게 배치했는지에 관계없이 멀티 부팅 헤더를 찾는 스캔을 시작합니다. 어셈블러/링커에서 멀티 바이트 헤더가 첫 번째 8k에 배치되고 4 바이트 정렬을 사용하는 한 원하는 모든 메커니즘을 사용할 수 있습니다. –