1. 程式人生 > >linux-0.11摳程式碼-bootsect

linux-0.11摳程式碼-bootsect

//bootfun.s
.global asm_message
.global asm_memmove
.global asm_readsector
.global asm_checkLBA
.code16

//extern void asm_memmove(void* src,void* des,int icount);
asm_memmove:
#源地址 ds:si 目的地址 es:di
	pushw %bp
	movw %sp,%bp
	#movw 6(%bp),%ax 第1個引數
	#movw 10(%bp),%bx 第2個引數
	#movw 14(%bp),%cx 第3個引數
1:
	movl 6(%bp),%eax
	movw %ax,%si
	movw $0,%ax
	movb $4,%cl
	shr %cl,%eax
	movw %ax,%ds
2:	
	movl 10(%bp),%eax
	movw %ax,%di
	movw $0,%ax
	movb $4,%cl
	shr %cl,%eax
	movw %ax,%es	
	movl 14(%bp),%ecx
	rep movsb
	
	movw	%bp,%sp
	popw	%bp
	ret
	
asm_checkLBA:
	movb $0x41,%ah
	movw $0x55aa,%bx
	int $0x13
	lahf 
	and $0x01,%ah
	xor $0x01,%ah
	ret
	
asm_message:
	pushl %ebp
	movl %esp,%ebp
	movl 8(%ebp),%eax
	movw %ax,%si
1:
	lodsb
	cmpb $0,%al
	je 1f
	movw $1,%bx
	movb $0xe,%ah
	int $0x10
	jmp 1b
1:
	movl	%ebp,%esp
	popl	%ebp
	ret
	
	
	#extern void asm_readsector(void* des,int driver ,int head,int track,int sector,int iCount);	
	;// 以下10行的用途是利用BIOS中斷INT 13h將setup模組從磁碟第2個扇區
	;// 開始讀到90200h開始處,共讀4個扇區。如果讀出錯,則復位驅動器,並
	;// 重試,沒有退路。
	;// INT 13h 的使用方法如下:
	;// ah = 02h - 讀磁碟扇區到記憶體;al = 需要讀出的扇區數量;
	;// ch = 磁軌(柱面)號的低8位;  cl = 開始扇區(0-5位),磁軌號高2位(6-7);
	;// dh = 磁頭號;				  dl = 驅動器號(如果是硬碟則要置為7);
	;// es:bx ->指向資料緩衝區;  如果出錯則CF標誌置位。 
asm_readsector:
	pushw %bp
	movw %sp,%bp
1:
	movl 6(%bp),%eax
	movw %ax,%bx
	movb $4,%cl
	movw $0, %ax
	shr %cl,%eax
	movw %ax,%es
	
	movb	14(%bp),%dh			;// drive 0, head 0
	movb	10(%bp),%dl			
	
	movb	18(%bp),%ch			;// sector 2, track 0
	movb	22(%bp),%cl
	
	movb $0x02,%ah
	movb 26(%bp),%al
	
	int $0x13
	jnc 1f
	movw $0,%dx
	movw $0,%ax
	int $0x13
	jmp	1b
1:	
	movw	%bp,%sp
	popw	%bp
	ret
	
//main.c
__asm__(".code16gcc\n");
//0x7c00 
extern void asm_checkLBA();
extern int asm_message (char * str);//申明彙編函式
extern void asm_memmove(void* src,void* des,int icount);
extern void asm_readsector(void* des,int driver ,int head,int track,int sector,int iCount);
extern unsigned short asm_readDisksectors(int driver);

char mbr[2] __attribute__((section(".mymbr"))) = {0x55,0xaa};
void entry(void)
{
	__asm__("movw $0x9000,%bx");
	__asm__("movw %bx,%ss");
	__asm__("movw $0xFF00,%bx");
	__asm__("movw %bx,%sp");
	asm_checkLBA();
	asm_message("Loading YoungOS......................");
	asm_readsector((void*)0x80200,0x80,0,0,2,4);
	
		
	__asm__("movw $0x8000,%bx");
	__asm__("movw %bx,%ds");
	__asm__("jmp $0x8000,$0x200");
}

linux.0.11 摳程式碼心得,實現多工輸出,這篇只是剛剛開始,只是說了引導部分~~~~~~~~還有後續心得~~~~~
程式碼閱讀工具:scitools understand(用了這個感覺 source insight 是浮雲,個人感覺,別噴)

程式碼編譯工:起初是vmware+ubuntu,後來才知道可以直接用cygwin,不過bootsect必須是真實linux環境,cygwin編譯出來的bin無法用objcopy轉換到小於512B的bin

自己用VS2010寫的二進位制寫磁碟工具,bintool.exe 原始檔,目標檔案,目標檔案偏移    (原來 linux dd命令就可以實現了,windows 有merge ,dd for windows)

虛擬機器:bochs vmware

除錯部分 gdb+vmware,bochs,其中gdb+vmware可以直接進行原始碼級除錯,具體方法可以另外諮詢我

先介紹幾個命令

gcc -c -g -nostdinc -fno-leading-underscore -fno-builtin -fno-stack-protector

-g 保留除錯資訊,供gdb除錯使用

-c 編譯目標檔案
-fno-builtin 不用自帶的c/c++庫函式
-fno-stack-protector 禁用堆疊保護

-fno-leading-underscore 函式匯出不加下劃線 ,當你申明一個test函式,匯出會成_test

簡化程式碼,把用匯編實現的都寫成功能程式碼函式,然後供.c檔案呼叫,知識點就是c語言和彙編互相呼叫

gcc -c -g -nostdinc -fno-leading-underscore -fno-builtin -fno-stack-protector main.c bootfun.s

 ld --entry=entry -Ttext=0x7c00  --section-start .mymbr=0x7dfe -o ./out/boot.elf main.o bootfun.o  -M >system.map   //生成elf檔案,此時elf帶gdb除錯資訊 注意不要加-s,-s會刪除除錯資訊 因為前面定義了.mybr的section ,55aa在512B mbr的偏移511處,所以0x7c00+511=0x7dfe

objcopy -I elf32-i386 -O binary ./out/boot.elf ./out/boot.bin   //將elf轉化成無格式的bin檔案

原始碼除錯方法,gdb boot.elf 進入gdb命令符,然後target remote localhost:8832  這裡要成功,自己網上搜一下 這麼用gdb+vmware除錯核心

程式碼部分

主要是

	asm_message("Loading YoungOS......................");
	asm_readsector((void*)0x80200,0x80,0,0,2,4);
	
		
	__asm__("movw $0x8000,%bx");
	__asm__("movw %bx,%ds");
	__asm__("jmp $0x8000,$0x200");
這幾句,其他應該沒用,當初測試沒刪掉

從磁碟2號扇區連續讀4個扇區內容到0x80200處,跳轉到0x80200

走過,路過,有手的捧個手場,不是擼,只要給個評論,給個賜教!!!!!!!!!!