//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
走过,路过,有手的捧个手场,不是撸,只要给个评论,给个赐教!!!!!!!!!!