歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

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);


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
自己用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  -o ./out/boot.elf main.o bootfun.o  -M >system.map  //生成elf文件,此時elf帶gdb調試信息 注意不要加-s,-s會刪除調試信息

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

windows 下 Bintool.exe boot.bin xxxx.img 0x000  (xxxx.img 為虛擬機的硬盤文件)// 注意 不要忘記 偏移510 511 寫成55AA,我是用ultraedit寫的,不然無法引導

源代碼調試方法,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

Copyright © Linux教程網 All Rights Reserved