你的位置:首页 > 操作系统

[操作系统]Linux内核系列—10.操作系统开发之内核HelloWorld


a.我们先来体验一下在Linux下用汇编编程的感觉,见代码

[section .data]	; 数据在此strHello	db	"Hello, world!", 0AhSTRLEN		equ	$ - strHello[section .text]	; 代码在此global _start	; 我们必须导出 _start 这个入口,以便让链接器识别_start:	mov	edx, STRLEN	mov	ecx, strHello	mov	ebx, 1	mov	eax, 4		; sys_write	int	0x80		; 系统调用	mov	ebx, 0	mov	eax, 1		; sys_exit	int	0x80		; 系统调用

编译方法:

nasm -f elf hello.asm -o hello.o

ld -m elf_i386 -s -o hello hello.o

./hello

运行结果是打印出Hello, world!

入口点默认的是_start,我们不但要定义它,而且要通过global这个关键字将它导出,这样链接程序才能找到它。两个系统调用不用深究,因为在我们自己的OS中根本用不到Linux的系统调用。

b.汇编和C同步使用

; 编译链接方法; (ld 的‘-s’选项意为“strip all”);; $ nasm -f elf foo.asm -o foo.o; $ gcc -c bar.c -o bar.o; $ ld -s hello.o bar.o -o foobar; $ ./foobar; the 2nd one; $extern choose	; int choose(int a, int b);[section .data]	; 数据在此num1st		dd	3num2nd		dd	4[section .text]	; 代码在此global _start	; 我们必须导出 _start 这个入口,以便让链接器识别global myprint	; 导出这个函数为了让 bar.c 使用_start:	push	dword [num2nd]	; `.	push	dword [num1st]	; |	call	choose		; | choose(num1st, num2nd);	add	esp, 8		; /	mov	ebx, 0	mov	eax, 1		; sys_exit	int	0x80		; 系统调用; void myprint(char* msg, int len)myprint:	mov	edx, [esp + 8]	; len	mov	ecx, [esp + 4]	; msg	mov	ebx, 1	mov	eax, 4		; sys_write	int	0x80		; 系统调用	ret	

1.由于在bar.c中用到函数myprint(),所以要用关键字global将其导出。

2.由于用到本文件外定义的函数choose(),所以要用关键字extern声明。

3.不管是myprint()还是choose(),遵循的都是C调用约定,后面的参数先入栈,并由调用者清理堆栈。

void myprint(char* msg, int len);int choose(int a, int b){	if(a >= b){		myprint("the 1st one\n", 13);	}	else{		myprint("the 2nd one\n", 13);	}	return 0;}

编译和执行的过程:

nasm -f elf -o foo.o foo.asm

gcc -m32 -c -o bar.o bar.c

ld -m elf_i386 -s -o foobar foo.o bar.o

./foobar

运行结果:the 2nd one

有了关键字global和extern就可以方便地在汇编和C代码之间自由来去。

 

一个码农的日常 

源码