linux-0.11摳程式碼-bootsect
阿新 • • 發佈:2019-02-01
//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
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
走過,路過,有手的捧個手場,不是擼,只要給個評論,給個賜教!!!!!!!!!!