gpt4 book ai didi

assembly - qemu 中的 irq 处理程序崩溃 : trying to execute code outside RAM or ROM

转载 作者:行者123 更新时间:2023-12-04 10:17:42 25 4
gpt4 key购买 nike

我一直在看内核开发教程,尤其是 bran's kernel ,我用 qemu 测试,或者用 -kernel-cdrom我要崩溃了。据我了解,这里会发生什么:
一旦我启用了中断( sti ),坑中断就会被我的 irq 处理程序捕获。我重用了 Bran 示例中的代码:

.intel_syntax noprefix
.global irq00
.extern_default_handler
irq00:
cli
push 0
push 32
jmp irq_common_stub
irq_common_stub:
pushad
push ds
push es
push fs
push gs
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
push eax
mov eax, irq_default_handler
call eax
etc...
add esp, 8
sti
iret

现在,当我启用 qemu 跟踪选项( -d cpu,exec,in_asm )时,我看到了:
IN:
0x0010121b: mov %eax, %fs
0x0010121d: mov %eax, %gs
0x0010121f: mov %esp, %eax
0x00101222: mov 0x100e81, %eax
0x00101227: call *%eax

Trace 0xb3aa3360 [0010121b]
EAX=83535657 EBX=00009500 ECX=0000000f EDX=00000000
ESI=00000000 EDI=0010a000 EBP=00000000 ESP=00107fc8
EIP=83535657 EFL=00000046 [---Z-P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00cf9300 DPL=0 DS [-WA]
CS =0008 00000000 ffffffff 00cf9300 DPL=0 CS32 [-R-]
SS =0008 00000000 ffffffff 00cf9300 DPL=0 DS [-WA]
DS =0008 00000000 ffffffff 00cf9300 DPL=0 DS [-WA]
FS =0008 00000000 ffffffff 00cf9300 DPL=0 DS [-WA]
GS =0008 00000000 ffffffff 00cf9300 DPL=0 DS [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT= 00108060 0000001f
IDT= 001080a0 0000071f
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000
DR6=ffff0ff0 DR7=00000400
CCS=00000000 CCD=00000000 CCO=SUBL
EFER=0000000000000000
qemu fatal: trying to execute code outside RAM or ROM at 0x83535657

最后一个 objdump -d kernel.bin让我检查一下,确实是我的
void irq_default_handler(isr_stack_frame_t sf);

C 函数位于我期望的地址:
00100e81 <irq_default_handler>

eax 和 eip 的值看起来很奇怪,但之前的 mov 显示了 C 函数的正确地址。
也许最后缺少的信息是以下结构:
 typedef struct {
uint32_t gs, ds, es, ds;
uint32_t edi, esi, ebp, ebx, edx, ecx, eax;
uint32_t int_number, err_code;
uint32_t eip, cs, eflags, useresp, ss;
} isr_stack_frame_t;

所以从那里不确定要去哪里。不知道我是如何从我的电话中得到错误的 eip 值的。特别是因为我也尝试直接调用 C 函数。任何建议或评论将是最受欢迎的。

最佳答案

我认为您的结构已关闭。

typedef struct {
uint32_t gs, ds, es, ds;
uint32_t edi, esi, ebp, ebx, edx, ecx, eax;
↑↑
uint32_t int_number, err_code;
uint32_t eip, cs, eflags, useresp, ss;
} isr_stack_frame_t;
pushad指令按操作码编码顺序(eax、ecx、edx、ebx、esp、ebp、esi、edi)推送所有八个 GPR。 (现在查看链接的教程,Bran 也有 esp。)

您缺少的另一件事是 mov eax,esp之前 push eax和电话: isr_stack_frame_t *您传递给 IRQ 处理程序的指针在您的情况下是错误的。您需要传递实际的帧地址 - 这是堆栈的顶部(底部),因为您刚刚使用推送将其组装到那里。

但是 +2 用于使用 .intel_syntax noprefix - 我不孤独!\o/

至于“良好的英特尔风格”,有点像@FrankKotler 已经说过的:永远不要写 mov eax,foo ;总是写 mov eax,offset foomov eax,[foo]不给意外混淆留下任何余地。

另一件事:你没有 sti直接在 iret 之前:EI/DI(中断)标志存储在EFLAGS中,由 iret恢复反正。因此,只需删除该行(Bran 也没有)。

关于assembly - qemu 中的 irq 处理程序崩溃 : trying to execute code outside RAM or ROM,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20753367/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com