学习笔记
使用教材(配书源码以及使用方法)
《一个64位操作系统的设计与实现》
http://www.ituring.com.cn/book/2450
https://www.jianshu.com/p/28f9713a9171
源码结构
- 配书代码包 :第4章 \ 程序 \ 程序4-9
程序4-9 运行结果
[anno@localhost bootloader]$ make
nasm boot.asm -o boot.bin
nasm loader.asm -o loader.bin
[anno@localhost kernel]$ make
gcc -E head.S > head.s
as --64 -o head.o head.s
gcc -E entry.S > entry.s
as --64 -o entry.o entry.s
gcc -mcmodel=large -fno-builtin -m64 -c main.c
gcc -mcmodel=large -fno-builtin -m64 -c printk.c
gcc -mcmodel=large -fno-builtin -m64 -c trap.c
gcc -mcmodel=large -fno-builtin -m64 -c memory.c
gcc -mcmodel=large -fno-builtin -m64 -c interrupt.c
ld -b elf64-x86-64 -z muldefs -o system head.o entry.o main.o printk.o trap.o memory.o interrupt.o -T Kernel.lds
objcopy -I elf64-x86-64 -S -R ".eh_frame" -R ".comment" -O binary system kernel.bin
[anno@localhost 4-9]$ ls
bochsrc boot.img bootloader kernel media
[anno@localhost 4-9]$ sudo mount boot.img media -t vfat -o loop
[anno@localhost 4-9]$ sudo cp bootloader/loader.bin media
[anno@localhost 4-9]$ sync
[anno@localhost 4-9]$ sudo cp bootloader/boot.bin media
[anno@localhost 4-9]$ sync
[anno@localhost 4-9]$ sudo cp kernel/kernel.bin media
[anno@localhost 4-9]$ sync
[anno@localhost 4-9]$ bochs -f ./bochsrc
程序4-9 源码阅读
代码清单 4-84 interrupt.c
#define IRQ_NAME2(nr) nr##_interrupt(void)
#define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr)
#define Build_IRQ(nr) \
void IRQ_NAME(nr); \
__asm__ ( SYMBOL_NAME_STR(IRQ)#nr"_interrupt: \n\t" \
"pushq $0x00 \n\t" \
SAVE_ALL \
"movq %rsp, %rdi \n\t" \
"leaq ret_from_intr(%rip), %rax \n\t" \
"pushq %rax \n\t" \
"movq $"#nr", %rsi \n\t" \
"jmp do_IRQ \n\t");
- 以
nr = 0x20
举例:
IRQ_NAME(0x20)
=>void IRQ0x20_interrupt(void);
之后是asm
部分代码
SYMBOL_NAME_STR(IRQ)#nr"_interrupt:
=>IRQ0x20_interrupt:
"movq $"#nr", %rsi
=>movq $0x20, %rsi
代码清单4-87 interrupt.c
void do_IRQ(unsigned long regs,unsigned long nr) //regs:rsp,nr
{
color_printk(RED,BLACK,"do_IRQ:%#08x\t",nr);
io_out8(0x20,0x20);
}
- 目前的中断处理函数就是 在屏幕上显示黑底红字的中断向量号,0x20号中断是时钟中断
-
io_out8(0x20,0x20);
: 向主8259A中断控制器发送EOI命令复位ISR寄存器
代码清单4-85 interrupt.c
Build_IRQ(0x20)
Build_IRQ(0x21)
Build_IRQ(0x22)
Build_IRQ(0x23)
. . .
void (* interrupt[24])(void)=
{
IRQ0x20_interrupt,
IRQ0x21_interrupt,
IRQ0x22_interrupt,
IRQ0x23_interrupt,
. . .
};
- 函数指针的数组,输入值是
void
且返回值也是void
的一类函数
lib.h
inline void io_out8(unsigned short port,unsigned char value)
{
__asm__ __volatile__( "outb %0, %%dx \n\t"
"mfence \n\t"
:
:"a"(value),"d"(port)
:"memory");
}
- 占位符
%0
等价于EAX = value
-
outb %0, %%dx
在这里等价于outb %ax, %dx
, 向端口dx
写入值ax
代码清单4-86 interrupt.c
void init_interrupt()
{
int i;
for(i = 32;i < 56;i++)
{
set_intr_gate(i , 2 , interrupt[i - 32]);
}
color_printk(RED,BLACK,"8259A init \n");
//8259A-master ICW1-4
io_out8(0x20,0x11);
io_out8(0x21,0x20);
io_out8(0x21,0x04);
io_out8(0x21,0x01);
//8259A-slave ICW1-4
io_out8(0xa0,0x11);
io_out8(0xa1,0x28);
io_out8(0xa1,0x02);
io_out8(0xa1,0x01);
//8259A-M/S OCW1
io_out8(0x21,0x00);
io_out8(0xa1,0x00);
sti();
}
- 外部硬件设备的中断向量号从
32
开始 :for(i = 32;i < 56;i++)
-
io_out8(0x20,0x11);
向端口0x20
写入数值0x11
参考资料
- 函数指针
[C指针]函数指针举例:C语言 完整源码
https://www.jianshu.com/p/992cbb3a55ce
- ATT 内联汇编 格式
[内联汇编]扩展asm:格式、占位符、跳转、内联汇编宏函数
https://www.jianshu.com/p/76fda24ee7f7
- _set_gate 格式化IDT描述符并填入IDT表
[OS64位][019]源码阅读:程序4-5 i=1/0 除法错误
https://www.jianshu.com/p/e14045176526
- MFENCE — Memory Fence
https://www.felixcloutier.com/x86/mfence
Does it make any sense to use the LFENCE instruction on x86/x86_64 processors?