【问题标题】:Jump to Protected Mode not working after linking the kernel链接内核后跳转到保护模式不起作用
【发布时间】:2014-10-05 23:33:36
【问题描述】:

我一直在开发引导加载程序,在链接文件之前将 c++ 代码链接到我的程序集 stage2 代码时遇到了问题,第二阶段将跳转到保护模式,然后跳转到长模式,没有任何问题,但现在在我链接之后跳转到保护模式时似乎有问题这是我用来跳转到保护模式的代码:

main:            
;first stage of bootloader is loaded at the address 0x07c0:0 
        ;second stage of bootloader is loaded at address 0x200:0x0 


        cli 
   xor ax, ax         ; All segments set to 0, flat memory model 
   mov ds, ax 
   mov es, ax 
   mov gs, ax 
   mov fs, ax 
   mov ss, ax 
   ; 
   ; Set stack top SS:0xffff 
   ; 
   mov sp, 0x0FFFF 
   ; 


        mov [CDDriveNumber], dl 

        SwitchToProtectedMode: 
        lgdt [GDT_32];load the gdt 

        call EnableA20 



        mov eax, cr0 
        or eax, 1 
        mov cr0, eax 


        ; Flush CS and set code selector 
        ;   

        jmp 0x8:Protected_Mode 

        [BITS 32];Declare 32 bits 

        Protected_Mode: 

这里是 GDT:

GDT_START: 
;null descriptor 
dd 0 
dd 0 
;data descriptor 
dw 0xFFFF 
dw 0 
db 0 
db 10011010b 
db 11001111b 
db 0 
;code descriptor 
dw 0xFFFF 
dw 0 
db 0 
db 10010010b 
db 11001111b 
db 0 
GDT_END: 
align 4 
GDT_32: 
dw GDT_END - GDT_START - 1 
dd GDT_START

这是我用来链接我的 c 代码和汇编代码的链接器脚本

KernAddr = 0x200;
ENTRY(_Start)
SECTIONS
{
    . = KernAddr;

    .text : AT(ADDR(.text) - KernAddr)
    {
        _code = .;
        *(.text)
        *(.rodata*)
        . = ALIGN(4096);
    }

   .data : AT(ADDR(.data) - KernAddr)
   {
        _data = .;
        *(.data)
        . = ALIGN(4096);
   }

   .eh_frame : AT(ADDR(.eh_frame) - KernAddr)
   {
       _ehframe = .;
       *(.eh_frame)
        . = ALIGN(4096);
   }

   .bss : AT(ADDR(.bss) - KernAddr)
   {
       _bss = .;
       *(.bss)

       /*
        * You usually need to include generated COMMON symbols
        * under kernel BSS section or use gcc's -fno-common
        */

        *(COMMON)
       . = ALIGN(4096);
   }

   _end = .;

   /DISCARD/ :
   {
        *(.comment)
   }
}

这是我为构建所有内容而制作的批处理程序:

nasm Stage1.asm -o Stage1.bin
nasm -f elf64 Stage2.asm -o Stage2.o
x86_64-elf-g++ -ffreestanding -mcmodel=large -mno-red-zone -mno-mmx -mno-sse -mno-sse2 -mno-sse3 -mno-3dnow -c -o kernel.o kernel.cpp
x86_64-elf-ld -T linkerscript.ld -o Anmu.bin Stage2.o kernel.o -nostdlib
copy Stage1.bin Root
copy Anmu.bin Root
mkisofs -b Stage1.bin -no-emul-boot -boot-info-table -o BootLoader.iso ./Root

其余代码可在此处获得:https://github.com/AnonymousUser1337/Anmu

【问题讨论】:

    标签: c++ assembly x86 nasm osdev


    【解决方案1】:

    你说 Stage2 是在 segment 0x0200 加载的,即地址 0x2000,但你的链接器说它从 offset 0x0200 开始。

    此外,尽管将您的输出命名为“Anmu.bin”,但您的文件实际上仍然是 ELF 可执行文件,这意味着文件中仍然存在所有标头和其他内容。相反,您需要使用objcopy 去除所有标头和调试符号,从而为您提供一个平面二进制文件:

    objcopy -S -O binary Anmu.bin Anmu-flat.bin
    

    现在,“Anmu-flat.bin”只是代码和数据,文件的第一个字节是第一条指令的开始。

    【讨论】:

    • 谢谢它的工作,但是如果它输出到一个平面二进制文件中它仍然是一个精灵可执行文件,它在链接它时它不会格式化它吗??
    • 不——链接仍然会产生一个 ELF 可执行文件(即使带有“.bin”扩展名)。
    • 好的,谢谢您的解释
    猜你喜欢
    • 2010-11-06
    • 1970-01-01
    • 2012-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-06
    • 1970-01-01
    相关资源
    最近更新 更多