跳转至保护模式时Boot Loader崩溃问题求助
启动Boot Loader进入32位模式时触发通用保护故障的问题
我在学习制作可运行的Boot Loader以启动C语言编写的内核,目前卡在执行远跳转进入32位代码(jmp CODE_SEG:init_32)的环节,执行到此处就崩溃。我使用GNU汇编器as编写代码,通过.intel_syntax切换为熟悉的Intel指令格式,此前所有步骤均正常。
Boot Loader代码
.intel_syntax .extern kernel_entry .globl _start .macro printstat a push %ax mov %ah, 0x0e mov %al, \a int 0x10 pop %ax .endm .macro printdblstat a, b push %ax mov %ah, 0x0e mov %al, \a int 0x10 mov %al, \b int 0x10 pop %ax .endm .code16 .section .text .extern kernel_entry KERNEL_ADDRESS = kernel_entry STACK = 0x9000 _start: mov drive, %dl # setup stack mov %bp, STACK mov %sp, %bp call load_drive jmp GDT_init # ;;;;;;;;;; Drive loader ;;;;;;;;;; load_drive: mov %al, 2 # read number of sectors (2) mov %ah, 0x02 # read mode mov %cl, 0x02 # start from sector 2 (sector 1 is boot sector) mov %ch, 0x00 # cylinder 0 mov %dl, drive mov %dh, 0x00 # head 0 # dl = drive number is set as input to disk_load # es:bx = buffer pointer is set as input as well mov %bx, 0x1000 # load into addr int 0x13 # BIOS interrupt (read disk) jc disk_error # check carry bit for error mov %dl, drive # disk cmp %al, 2 # read 2 sectors? ret # sector error mov %bl, %al printstat %bl printdblstat 'E', '1' jmp . # disk error disk_error: printdblstat 'E', '2' jmp . # ;;;; # ;;;;;;;;;;; GDT ;;;;;;;;;;;; .section .data .align 8 drive: .byte 0 gdt_start: .4byte 0x0,0x0 gdt_code: .byte 0xFF,0xFF,0x0,0x0,0x0,0b10011010,0b11001111,0x0 gdt_data: .byte 0xFF,0xFF,0x0,0x0,0x0,0b10010010,0b11001111,0x0 gdt_video: .byte 0xFF,0xFF,0x0,0x80,0x0B,0b10010010,0b01000000,0x0 gdt_end: gdt_descriptor: .word gdt_end - gdt_start - 1 # size (16 bit) .4byte gdt_start # address (32 bit) CODE_SEG = gdt_code - gdt_start DATA_SEG = gdt_data - gdt_start VIDEO_SEG = gdt_video - gdt_start .section .text # ;;;;;;;;;; Init GDT ;;;;;;;;;; GDT_init: lgdt gdt_descriptor xor %ax, %ax mov %ds, %ax mov %ss, %ax in %al,0x70 or %al,0x80 out 0x70, %al # nonmasked interrupts in %al,0x92 or %al,2 out 0x92, %al # A20 line cli mov %eax, %cr0 or %al, 0x1 # protected mode mov %cr0, %eax jmp CODE_SEG:init_32 # <================================== crashes here # ;;;;;;;;;;; 32 bit mode ;;;;;;;;;; .code32 .align 32 init_32: mov %ax, DATA_SEG mov %ds, %ax mov %ss, %ax mov %es, %ax mov %fs, %ax mov %gs, %ax mov %ebp, STACK mov %esp, %ebp call kernel_entry hlt .space 510-(.-_start) .word 0xAA55 # magic number
QEMU -d cpu-reset 日志输出
CPU Reset (CPU 0) EAX=00000000 EBX=00000000 ECX=00000000 EDX=00000663 ESI=00000000 EDI=00000000 EBP=00000000 ESP=00000000 EIP=0000fff0 EFL=00000002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0 ES =0000 00000000 0000ffff 00009300 CS =f000 ffff0000 0000ffff 00009b00 SS =0000 00000000 0000ffff 00009300 DS =0000 00000000 0000ffff 00009300 FS =0000 00000000 0000ffff 00009300 GS =0000 00000000 0000ffff 00009300 LDT=0000 00000000 0000ffff 00008200 TR =0000 00000000 0000ffff 00008b00 GDT= 00000000 0000ffff IDT= 00000000 0000ffff CR0=60000010 CR2=00000000 CR3=00000000 CR4=00000000 DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000 DR6=ffff0ff0 DR7=00000400 CCS=00000000 CCD=00000000 CCO=DYNAMIC EFER=0000000000000000 FCW=037f FSW=0000 [ST=0] FTW=00 MXCSR=00001f80 FPR0=0000000000000000 0000 FPR1=0000000000000000 0000 FPR2=0000000000000000 0000 FPR3=0000000000000000 0000 FPR4=0000000000000000 0000 FPR5=0000000000000000 0000 FPR6=0000000000000000 0000 FPR7=0000000000000000 0000 XMM00=0000000000000000 0000000000000000 XMM01=0000000000000000 0000000000000000 XMM02=0000000000000000 0000000000000000 XMM03=0000000000000000 0000000000000000 XMM04=0000000000000000 0000000000000000 XMM05=0000000000000000 0000000000000000 XMM06=0000000000000000 0000000000000000 XMM07=0000000000000000 0000000000000000 Triple fault
QEMU -d int 日志输出
check_exception old: 0xd new 0xd 1: v=08 e=0000 i=0 cpl=0 IP=0000:00007c70 pc=00007c70 SP=0000:00009000 env->regs[R_EAX]=00000011 EAX=00000011 EBX=00001000 ECX=00000002 EDX=00000080 ESI=00000000 EDI=00000000 EBP=00009000 ESP=00009000 EIP=00007c70 EFL=00000006 [-----P-] CPL=0 II=0 A20=1 SMM=0 HLT=0 ES =0000 00000000 0000ffff 00009300 DPL=0 DS16 [-WA] CS =0000 00000000 0000ffff 00009b00 DPL=0 CS16 [-RA] SS =0000 00000000 0000ffff 00009300 DPL=0 DS16 [-WA] DS =0000 00000000 0000ffff 00009300 DPL=0 DS16 [-WA] FS =0000 00000000 0000ffff 00009300 DPL=0 DS16 [-WA] GS =0000 00000000 0000ffff 00009300 DPL=0 DS16 [-WA] LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy GDT= 00000000 00000000 IDT= 00000000 000003ff CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000 DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000 DR6=ffff0ff0 DR7=00000400 CCS=00000002 CCD=00000011 CCO=LOGICB EFER=0000000000000000 check_exception old: 0x8 new 0xd
编译命令
gcc -Wl,--oformat=binary -Wl,\ -Ttext=0x7c00 -Wl,--build-id=none -Wl,-melf_i386 \ -nostartfiles -nostdlib -fno-pie -O0 -ffreestanding \ -m32 -o /tmp/lima/final.bin bootloader/boot.s kernel/entry.c
根据CPU故障码0xd,这是通用保护故障(General Protection Fault),随后触发了三重故障。请问这是GDT配置错误导致的吗?还是有其他可能的原因?
内容的提问来源于stack exchange,提问作者Sir Archibald Humphrey
相关产品推荐
相关产品推荐

