冬天OS(四):使用 C 语言

--------------------------------------------------------

用 C 重新设置 GDT

--------------------------------------------------------

 

上节我们 jmp 到了 kernel ,那是用汇编写的 kernel ,只是编译成了 elf 格式的目标文件,为什么要将一个汇编 kernel 编译成 elf 呢?因为我们打算汇编和 C 一起结合编译,而这种编译方法最终生成的就是 elf 格式的目标文件!这节我们来用一用 C 语言,C 语言和汇编语言能相互调用是一件特别爽的事情...

 

一,重新设置 GDT 表的位置
本来 GDT 在 loader.bin 中,因为跳转到保护模式需要用到 GDT,所以临时设置到了 loader.bin 中,但那仅仅是个 loader,因此我们来将 GDT ‘正名’到 C 内核中!——GDT 的内容还是一样的,只是位置挪到了 kernel 中!
 

; ----------------------------
; <kernel.asm>
; Jack Zheng 11.27
; ----------------------------

SELECTOR_KERNEL_CS	equ	8

; ----
; in C file
; ----
extern	cstart
extern 	gdt_ptr

[SECTION .bss]
StackSpace	resb	2 * 1024
StackTop:
[section .text]
global	_start
_start:
	; ----
	; ss regidter is already set orign 0
	; ----
	mov	esp, StackTop
	sgdt	[gdt_ptr]
	call	cstart
	lgdt	[gdt_ptr]
	jmp	SELECTOR_KERNEL_CS:csinit
csinit:
	mov	ah, 0fh
	mov	al, 'N'
	mov	[gs:(80*2*17)], ax
	jmp 	$
// ----------------------------
// <protect.h>
// Jack Zheng 11.27
// ----------------------------
#ifndef _TINIX_PROTECT_H_
#define _TINIX_PROTECT_H_

typedef struct s_descriptor
{
	t_16	limit_low;
	t_16	base_low;
	t_8	base_mid;
	t_8	attr1;
	t_8	limit_high_attr2;
	t_8	base_high;	
}DESCRIPTOR;

#endif
// ----------------------------
// <type.h>
// Jack Zheng 11.27
// ----------------------------

#ifndef	_TINIX_TYPE_H_
#define	_TINIX_TYPE_H_

typedef	unsigned int	t_32;
typedef unsigned short	t_16;
typedef unsigned char	t_8;

#endif
// ----------------------------
// <const.h>
// Jack Zheng 11.27
// ----------------------------
#ifndef	_TINIX_CONST_H_
#define _TINIX_CONST_H_

#define PUBLIC		
#define PRIVATE		static
#define	GDT_SIZE	128

#endif
// ----------------------------
// <start.c>
// Jack Zheng 11.27
// ----------------------------
#include "type.h"
#include "const.h"
#include "protect.h"

// asm func
PUBLIC	void * memcpy(void * pDst, void * pSrc, int iSize);

PUBLIC	t_8		gdt_ptr[6];
PUBLIC	DESCRIPTOR	gdt[GDT_SIZE];

PUBLIC	void cstart()
{
	// copy old gdt to new gdt
	memcpy(&gdt, (void *)(*(t_32 *)(&gdt_ptr[2])), *((t_16 *)(&gdt_ptr[0])));

	// prepare to assign new gdt info to gdt register!
	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);
	*p_gdt_base	= (t_32)&gdt;
}
; ----------------------------
; <string.asm>
; Jack Zheng 11.27
; ----------------------------
[SECTION .text]


global	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 结束 ----------------------------

可以看到我们的新 GDT 设置成功了,并且最后打印了N !

 

二,添加一个打印函数 disp_str

; ----------------------------
; <klib.asm>
; Jack Zheng 11.27
; ----------------------------
[SECTION .data]
disp_pos	dd 0
[SECTION .text]

global	disp_str
; ----------------------------
; void disp_str(char * info);
; ----------------------------
disp_str:
	push	ebp
	mov	ebp, esp

	mov	esi, [ebp + 8]	; pszInfo
	mov	edi, [disp_pos]
	mov	ah, 0Fh
.1:
	lodsb
	test	al, al
	jz	.2
	cmp	al, 0Ah	; 是回车吗?
	jnz	.3
	push	eax
	mov	eax, edi
	mov	bl, 160
	div	bl
	and	eax, 0FFh
	inc	eax
	mov	bl, 160
	mul	bl
	mov	edi, eax
	pop	eax
	jmp	.1
.3:
	mov	[gs:edi], ax
	add	edi, 2
	jmp	.1

.2:
	mov	[disp_pos], edi

	pop	ebp
	ret
// ----------------------------
// <start.c>
// Jack Zheng 11.27
// ----------------------------
#include "type.h"
#include "const.h"
#include "protect.h"

// asm func
PUBLIC	void * memcpy(void * pDst, void * pSrc, int iSize);
PUBLIC 	void disp_str(char * pszInfo);

PUBLIC	t_8		gdt_ptr[6];
PUBLIC	DESCRIPTOR	gdt[GDT_SIZE];

PUBLIC	void cstart()
{
	disp_str("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n-----\"cstart\" begins-----\n");
	// copy old gdt to new gdt
	memcpy(&gdt, (void *)(*(t_32 *)(&gdt_ptr[2])), *((t_16 *)(&gdt_ptr[0])));

	// prepare to assign new gdt info to gdt register!
	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);
	*p_gdt_base	= (t_32)&gdt;
}

disp_str successful!!!

 

OK ,到现在我们算是正式进入内核开发的主要阶段了,但是在大展身手之前,我们先要组织一下我们的文件,因为它看起来太乱了...

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

柔弱胜刚强.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值