kernel.asm部分
sgdt [gdt_ptr] ; cstart() 中将会用到 gdt_ptr
call cstart ; 在此函数中改变了gdt_ptr,让它指向新的GDT
lgdt [gdt_ptr] ; 使用新的GDT
使用命令将gdt地址复制到新的gdt处。
cstart.c部分
PUBLIC t_8 gdt_ptr[6]; // 0~15:Limit 16~47:Base
PUBLIC DESCRIPTOR gdt[GDT_SIZE];
char *str0 = "hello os world, last line";
char *str1 = "hello os world, line111\n";
static char buf[1024]; // 显示用临时缓冲区
/*======================================================================*/
PUBLIC void cstart(){
//DspStrFixPos((80*20+0)*2, str0);
sprintf(buf, "hello os printk year is %d, month is %d, day is %d\n", 2020, 11, 8);
memccpy_gdt();
DspStrFixPos((80*24+0)*2, buf);
//sprintf(buf, "hello os printk year is %d, month is %d, day is %d\n", 2020, 11, 8);
//DspStrFixPos(12, buf);
//sprintf(buf, "hello os sprintf, time is %d:%d\n", 14, 38);
//DspStrFixPos(13, buf);
}
PUBLIC void memccpy_gdt() {
// 将 LOADER 中的 GDT 复制到新的 GDT 中
memcpy( &gdt, // New GDT
(void*)(*((t_32*)(&gdt_ptr[2]))), // Base of Old GDT
*((t_16*)(&gdt_ptr[0])) + 1 // Limit of Old GDT
);
// gdt_ptr[6] 共 6 个字节:0~15:Limit 16~47:Base。用作 sgdt 以及 lgdt 的参数。
t_16* p_gdt_limit = (t_16*)(&gdt_ptr[0]);
t_32* p_gdt_base = (t_32*)(&gdt_ptr[2]);
*p_gdt_limit = GDT_SIZE * sizeof(DESCRIPTOR) - 1;
*p_gdt_base = (t_32)&gdt;
}
memcpy
; ------------------------------------------------------------------------
; void* memcpy(void* es:pDest, void* ds:pSrc, int iSize);
; ------------------------------------------------------------------------
memcpy:
push ebp
mov ebp, esp
push esi
push edi
push ecx
mov edi, [ebp + 8] ; Destination
mov esi, [ebp + 12] ; Source
mov ecx, [ebp + 16] ; Counter
.1:
cmp ecx, 0 ; 判断计数器
jz .2 ; 计数器为零时跳出
mov al, [ds:esi] ; ┓
inc esi ; ┃
; ┣ 逐字节移动
mov byte [es:edi], al ; ┃
inc edi ; ┛
dec ecx ; 计数器减一
jmp .1 ; 循环
.2:
mov eax, [ebp + 8] ; 返回值
pop ecx
pop edi
pop esi
mov esp, ebp
pop ebp
ret ; 函数结束,返回
; memcpy 结束-------------------------------------------------------------
网友评论