【发布时间】: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