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

说说linux0.11的bootsect.s 

Linux源码学习--bootsect.s启动

Linux 2.4.0 内核bootsect.S文件完全注释

Linux0.11内核--启动引导代码分析bootsect.s 

相关内容

    暂无相关文章