c++ - 链接内核后跳转到保护模式不起作用

标签 c++ assembly x86 nasm osdev

我一直在开发引导加载程序,在链接文件之前将 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

最佳答案

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

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

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

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

关于c++ - 链接内核后跳转到保护模式不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25272080/

相关文章:

c++ - 从另一个 HBITMAP 复制位图

c++ - 这不应该使用回溯算法吗?

c - 汇编代码转C代码(添加指令问题)

assembly - MOVSX汇编指令如何工作?

c++ - 原子结构的统一初始化?

c++ - 循环中奇怪的指针行为

assembly - 四元运算符和长运算符有什么区别

assembly - 为什么我的汇编输出位于字母位置? (1+1=b)

c++ - 汇编代码的输出 - 与 add 混淆?

c++ - 使用 __m64 引用将 C++ 项目转换为 x64