學(xué)習(xí)筆記
使用教材(配書(shū)源碼以及使用方法)
《一個(gè)64位操作系統(tǒng)的設(shè)計(jì)與實(shí)現(xiàn)》
http://www.ituring.com.cn/book/2450
http://www.reibang.com/p/28f9713a9171
源碼結(jié)構(gòu)
- 配書(shū)代碼包 :第4章 \ 程序 \ 程序4-9
程序4-9 運(yùn)行結(jié)果
[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 運(yùn)行結(jié)果
程序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);
}
- 目前的中斷處理函數(shù)就是 在屏幕上顯示黑底紅字的中斷向量號(hào)僻造,0x20號(hào)中斷是時(shí)鐘中斷
-
io_out8(0x20,0x20);
: 向主8259A中斷控制器發(fā)送EOI命令復(fù)位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,
. . .
};
- 函數(shù)指針的數(shù)組,輸入值是
void
且返回值也是void
的一類(lèi)函數(shù)
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
等價(jià)于EAX = value
-
outb %0, %%dx
在這里等價(jià)于outb %ax, %dx
坪仇, 向端口dx
寫(xiě)入值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();
}
- 外部硬件設(shè)備的中斷向量號(hào)從
32
開(kāi)始 :for(i = 32;i < 56;i++)
-
io_out8(0x20,0x11);
向端口0x20
寫(xiě)入數(shù)值0x11
參考資料
- 函數(shù)指針
[C指針]函數(shù)指針舉例:C語(yǔ)言 完整源碼
http://www.reibang.com/p/992cbb3a55ce
- ATT 內(nèi)聯(lián)匯編 格式
[內(nèi)聯(lián)匯編]擴(kuò)展asm:格式栏笆、占位符、跳轉(zhuǎn)做入、內(nèi)聯(lián)匯編宏函數(shù)
http://www.reibang.com/p/76fda24ee7f7
- _set_gate 格式化IDT描述符并填入IDT表
[OS64位][019]源碼閱讀:程序4-5 i=1/0 除法錯(cuò)誤
http://www.reibang.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?