【问题标题】:Getting C to wok with assembly让 C 开始组装
【发布时间】:2021-08-06 06:57:31
【问题描述】:

我正在开发一个简单的操作系统,在过去的 3 周里,我一直在调试一个错误,该错误仅在我在程序集中调用 c++ 或 c 代码时出现,qemu(我正在使用的模拟器)将开始闪烁并且不会加载代码。我已经在其他模拟器上试过了。

“Bootloader.asm”

    [org 0x7c00]
    mov ah, 0x00
    mov al, 0x03
    int 0x10
    mov [Boot_Disk], dl
    
    mov bp, 0x7c00
    mov sp, bp
    
    call DiskRead
    
    jmp Program_Space
    
    jmp $
    
    %include "ReadDisk.asm"
    
    
    times 510 - ($ - $$) db 0 ;fills the rest of the bytes till byte 510 with 0s
    db 0x55 ;sets the last 2 bytes to 0x55 and 0xaa, so the bios knows its bootable
    db 0xaa

“Sector2.asm”

jmp Enable32BitMode
%include "gdt.asm"
Enable32BitMode:

    call enable_A20

    cli ;disables interupts

    lgdt [gdt_descriptor]

    mov eax, cr0 
    or eax, 1       ; set PE (Protection Enable) bit in CR0 (Control Register 0)
    mov cr0, eax
    jmp codeseg:Start32Bit



enable_A20:
    in al, 0x92
    or al, 2
    out 0x92, al
    ret       



[bits 32]
;[extern _start]
Start32Bit:

    mov ax, dataseg ;moves dataseg (found in gdt, into registers ds to gs)
    mov ds, ax
    mov ss, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
    ;mov [0xb8000], byte 'h'
  ;  call _start
    jmp $

times 2048 - ($-$$) db 0 ;fills the disk with 2kb of 0's

“ReadDisk.asm”

    Program_Space equ 0x7e00
    
    DiskRead:
        mov ah, 0x02 
        mov bx, Program_Space 
        mov al, 4 ;amount of sectors to read
        mov dl, [Boot_Disk] 
        mov ch, 0x00 ; 
        mov dh, 0x00 ; 
        mov cl, 0x02 ;
    
        int 0x13

"ReadText.cpp"


    extern "C" void _start() {
        return;
    }

我的编译器选项(linux):

    nasm Bootloader.asm -f bin -o Bootloader.bin 
    nasm Sector2.asm -f elf32 -o Sector2.o
    gcc -ffreestanding -m32 -mno-red-zone -march=i686 -c "Kernel.c" -o "ReadText.o" # -m32

    ld -m elf_i386 -o Kernel.tmp -Ttext 0x7e00 Sector2.o ReadText.o
    objcopy -O binary Kernel.tmp Kernel.bin 
    cat Bootloader.bin Kernel.bin > Bootloader.flp

c代码的反汇编:

Disassembly of section .text:



00000000 <_start>:

  0:   f3 0f 1e fb             endbr32 

  4:   55                      push   %ebp

  5:   89 e5                   mov    %esp,%ebp

  7:   90                      nop

  8:   5d                      pop    %ebp

  9:   c3                      ret    

【问题讨论】:

  • 使用edit 链接并使用代码按钮修复格式。你的DiskRead 似乎没有回来。您似乎没有设置段寄存器。您似乎试图在 16 位模式下运行 32 位代码(可能适用于您的空函数)。显然,即使您的 Sector2 也被组装为 32 位......现在这绝对行不通。
  • 我忘了添加我的一个文件 :D
  • 您需要一个堆栈才能call 任何东西,尤其是 C 代码。切换到保护模式后不应该设置esp吗?
  • 此外,我相信-f elf32 会自动选择[bits 32],因此您应该在文件顶部放置[bits 16] 以正确组装16 位部分。确保 C 代码没有堆栈保护金丝雀之类的东西(验证反汇编)。
  • 顺便说一句,模拟器有调试器(使用它们的主要好处之一),所以您应该能够单步执行您的引导代码并查看它在哪里中断。在这方面,Bochs 的调试器比 qemu 更好。

标签: c++ assembly operating-system


【解决方案1】:

喜欢@jester 评论了您的问题。您似乎将引导加载程序编译为 .code32。您的 CPU(qemu 或任何其他 VM)不会启动它,因为 CPU 最初以 16 位模式运行。请看这里-JOS bootloader。这是您可以从中学习的极简引导加载程序。

【讨论】:

  • 将 [bits 16] 添加到顶部不起作用,这是您的意思吗?
  • @Kalix 我认为 saym 指的是扇区 2 文件。文件的顶部必须以 16 位模式运行。
  • @Kalix 你能分享你反汇编的 C 文件吗? (为了简单起见,最好将其保留为 C)。也尝试使用“fno-pie”标志编译你的 C 代码。
  • @saidm 我试过了,它没有改变任何东西,我在问题中添加了拆解。
  • @Kalix,对不起,我看不出你在哪里设置你的堆栈(sp/esp reg)。通常你最好把 0x7b00 放在你的堆栈指针寄存器中(它会向下增长)。此外,使用-fcf-protection=none 禁用 Intel CET(但 CPU 必须忽略这些指令)更安全
【解决方案2】:

我发现了错误,我没有读取保存 C 代码的扇区,如果您正在阅读此问题,请确保您正在阅读所有扇区。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-13
    • 1970-01-01
    • 2012-07-30
    • 2020-03-01
    • 1970-01-01
    相关资源
    最近更新 更多