assembly - 如何在 32 位内核中静态定义低 16 位地址的 IDT(使用 gcc 内联汇编)
问题描述
我在 NASM 中有以下代码,该代码针对该问题进行了缩写:
idt_start:
int0:
dw isr0
dw 0x0008
db 0x00
db 10001110b
dw 0x0000
idt_end:
idtr:
dw idt_end - idt_start - 1
dd idt_start
isr0:
通常我有 47 个条目,其中 32 个用于保护模式异常,15 个用于映射 IRQ。我正在设置一个 IDT 来管理来自我的引导加载程序的中断。
当我尝试将此代码移植到 C++ 内联汇编时,就会出现问题。
我有 2 个文件 kernel.cpp:
#include "idt.h"
void kmain(){
defineIDT();
halt:;
asm("hlt");
goto halt;
}
和 idt.cpp:
void defineIDT(){
asm(
"idt_start:\n\t"
"int0:\n\t"
".hword isr0\n\t"
".hword 0x0008\n\t"
".byte 0x00\n\t"
".byte 0b10001110\n\t"
".hword 0x0000\n\t"
"idt_end:\n\t"
"idtr:\n\t"
".hword idt_end - idt_start - 1\n\t"
".word idt_start\n\t"
"isr0:\n\t"
);
return;
}
我正在使用 g++ 编译我的代码g++ -static -ffreestanding -nostdlib -znoexecstack -mno-red-zone -s -m32 kernel.cpp idt.cpp -okernel.o
我收到一条错误消息relocation truncated to fit: R_386_16 against `.text'
。这是因为.hword isr0
,.hword idt_end - idt_start - 1
和.word idt_start
行。我看不出还有其他方法可以实现这一点。
解决方案
我最终做了以下事情:
我用 NASM 初始化了 IDT。
extern routine33
bits 32
lidt[idtr]
sti
halt:
hlt
jmp halt
idt_start:
int0:
dw isr0
dw 0x0008
db 0x00
db 10001110b
dw 0x0000
int1:
dw isr1
dw 0x0008
db 0x00
db 10001110b
dw 0x0000
int2:
dw isr2
dw 0x0008
db 0x00
db 10001110b
dw 0x0000
int3:
dw isr3
dw 0x0008
db 0x00
db 10001110b
dw 0x0000
int4:
dw isr4
dw 0x0008
db 0x00
db 10001110b
dw 0x0000
int5:
dw isr5
dw 0x0008
db 0x00
db 10001110b
dw 0x0000
int6:
dw isr6
dw 0x0008
db 0x00
db 10001110b
dw 0x0000
int7:
dw isr7
dw 0x0008
db 0x00
db 10001110b
dw 0x0000
int8:
dw isr8
dw 0x0008
db 0x00
db 10001110b
dw 0x0000
int9:
dw isr9
dw 0x0008
db 0x00
db 10001110b
dw 0x0000
int10:
dw isr10
dw 0x0008
db 0x00
db 10001110b
dw 0x0000
int11:
dw isr11
dw 0x0008
db 0x00
db 10001110b
dw 0x0000
int12:
dw isr12
dw 0x0008
db 0x00
db 10001110b
dw 0x0000
int13:
dw isr13
dw 0x0008
db 0x00
db 10001110b
dw 0x0000
int14:
dw isr14
dw 0x0008
db 0x00
db 10001110b
dw 0x0000
int15:
dw isr15
dw 0x0008
db 0x00
db 10001110b
dw 0x0000
int16:
dw isr16
dw 0x0008
db 0x00
db 10001110b
dw 0x0000
int17:
dw isr17
dw 0x0008
db 0x00
db 10001110b
dw 0x0000
int18:
dw isr18
dw 0x0008
db 0x00
db 10001110b
dw 0x0000
int19:
dw isr19
dw 0x0008
db 0x00
db 10001110b
dw 0x0000
int20:
dw isr20
dw 0x0008
db 0x00
db 10001110b
dw 0x0000
int21:
dw isr21
dw 0x0008
db 0x00
db 10001110b
dw 0x0000
int22:
dw isr22
dw 0x0008
db 0x00
db 10001110b
dw 0x0000
int23:
dw isr23
dw 0x0008
db 0x00
db 10001110b
dw 0x0000
int24:
dw isr24
dw 0x0008
db 0x00
db 10001110b
dw 0x0000
int25:
dw isr25
dw 0x0008
db 0x00
db 10001110b
dw 0x0000
int26:
dw isr26
dw 0x0008
db 0x00
db 10001110b
dw 0x0000
int27:
dw isr27
dw 0x0008
db 0x00
db 10001110b
dw 0x0000
int28:
dw isr28
dw 0x0008
db 0x00
db 10001110b
dw 0x0000
int29:
dw isr29
dw 0x0008
db 0x00
db 10001110b
dw 0x0000
int30:
dw isr30
dw 0x0008
db 0x00
db 10001110b
dw 0x0000
int31:
dw isr31
dw 0x0008
db 0x00
db 10001110b
dw 0x0000
int32:
dw isr32
dw 0x0008
db 0x00
db 10001110b
dw 0x0000
int33:
dw isr33
dw 0x0008
db 0x00
db 10001110b
dw 0x0000
int34:
dw isr34
dw 0x0008
db 0x00
db 10001110b
dw 0x0000
int35:
dw isr35
dw 0x0008
db 0x00
db 10001110b
dw 0x0000
int36:
dw isr36
dw 0x0008
db 0x00
db 10001110b
dw 0x0000
int37:
dw isr37
dw 0x0008
db 0x00
db 10001110b
dw 0x0000
int38:
dw isr38
dw 0x0008
db 0x00
db 10001110b
dw 0x0000
int39:
dw isr39
dw 0x0008
db 0x00
db 10001110b
dw 0x0000
int40:
dw isr40
dw 0x0008
db 0x00
db 10001110b
dw 0x0000
int41:
dw isr41
dw 0x0008
db 0x00
db 10001110b
dw 0x0000
int42:
dw isr42
dw 0x0008
db 0x00
db 10001110b
dw 0x0000
int43:
dw isr43
dw 0x0008
db 0x00
db 10001110b
dw 0x0000
int44:
dw isr44
dw 0x0008
db 0x00
db 10001110b
dw 0x0000
int45:
dw isr45
dw 0x0008
db 0x00
db 10001110b
dw 0x0000
int46:
dw isr46
dw 0x0008
db 0x00
db 10001110b
dw 0x0000
int47:
dw isr47
dw 0x0008
db 0x00
db 10001110b
dw 0x0000
idt_end:
idtr:
dw idt_end - idt_start - 1
dd idt_start
isr0:
iret
isr1:
iret
isr2:
iret
isr3:
iret
isr4:
iret
isr5:
iret
isr6:
iret
isr7:
iret
isr8:
iret
isr9:
iret
isr10:
iret
isr11:
iret
isr12:
iret
isr13:
iret
isr14:
iret
isr15:
iret
isr16:
iret
isr17:
iret
isr18:
iret
isr19:
iret
isr20:
iret
isr21:
iret
isr22:
iret
isr23:
iret
isr24:
iret
isr25:
iret
isr26:
iret
isr27:
iret
isr28:
iret
isr29:
iret
isr30:
iret
isr31:
iret
isr32:
iret
isr33: ;mappped to IRQ 1 for Keyboard interrupt
call routine33
iret
isr34:
iret
isr35:
iret
isr36:
iret
isr37:
iret
isr38:
iret
isr39:
iret
isr40:
iret
isr41:
iret
isr42:
iret
isr43:
iret
isr44:
iret
isr45:
iret
isr46:
iret
isr47:
iret
然后我在 idt.cpp 中写了一个 C++ 函数:
void print(){
asm("movw $0x0770, (0xb8000)");
}
extern "C" void routine33(){
print();
return;
}
我用 bash 脚本编译并链接结果:
#!/bin/bash
g++ -static -ffreestanding -znoexecstack -nostdlib -mno-red-zone -s -c -m32 idt.cpp -oidt.o
nasm -felf32 second_stage_bootloader.asm -osecond_stage_bootloader.o
ld -melf_i386 -static -pie --no-dynamic-linker -nostdlib --strip-all -Ttext=0x8000 second_stage_bootloader.o idt.o -o kernel.elf
objcopy --only-section=.text --output-target binary kernel.elf kernel.bin
dd if=/dev/zero of=disk.img bs=512 count=100 && dd if=bootloader.bin of=disk.img conv=notrunc && dd if=kernel.bin seek=1 bs=512 of=disk.img conv=notrunc
然后我使用 BIOS 中断将生成的普通二进制文件加载到我的引导加载程序中的 RAM 到 0x8000。我使用 跳转到代码jmp 0x08:0x8000
。
我启动整个事情:
qemu-system-x86_64 -drive file=disk.img,format=raw,index=0,media=disk -s
.
当我按下一个键时,它会在 0xb8000 处打印一个白色的“p”。
推荐阅读
- apache-kafka-streams - Kafka 流 DSL 标头支持
- amazon-web-services - 多个并行 AWS Lambda 调用
- twitter - 启用使用 Twitter 登录 - 回调 URL
- r - 如何防止专有的 R 包被同名的 CRAN 包更新和替换?
- python - MySQL Python 连接器失败
- android - Android 录像机应用程序 - “视频无法播放”错误
- mysql - 在 mariaDB 中使用 BLOB 与 TEXT(检索和插入速度)有什么区别
- java - Reactor:检测空信号以对空单声道起作用
- authentication - 如何使用他的密钥在本地 gitlab 中找到用户
- javascript - 如何在 IE 11 中将变量从一个浏览器窗口传递到另一个浏览器窗口(同一浏览器)?