从零开始搭建环境编写操作系统 AT&T GCC (一)搭建环境和测试环境
来源:互联网 发布:淘宝最新刷销量方法 编辑:程序博客网 时间:2024/06/04 07:49
又有闲时间了,一直没有在x86的计算机上做过裸机编程,只要闲下来就手痒,去买了本《30天自制操作系统》,因为之前听说过这本书,而且是在x86的windows电脑上做的,所以就买来研读了一番,之前写的东西也只在群里共享了,这次正好想开个博客,剩下有一年的闲时间可以打理一下这个博客。所以说,这是第一篇文章,我不去照搬照抄书上的内容,我只是参考一下它搭建的过程,所有我操作的过程我会记下来放在这里,以后给自己和大家能有一个参考,毕竟GCC编写操作系统和AT&T汇编这方面的资料太少了。
作为一个忠实的linux用户,我的操作系统在linux上搭建,具体点说是ubuntu,而且有很多地方我写的比较粗,还是得有一定linux基础的小伙伴来看这些文章。有不太懂的或者我写错的地方,可以直接评论区回复,我会尽可能的回答。
创建一个文件夹,以后这就是操作系统的诞生地了,我起的名字是OranOS
一、罗列一下要用的工具
编译器:GCC,具体说是as、ld和gcc,这三个经常写硬件的小伙伴应该是耳熟能详了,第一个是AT&T格式的汇编器,第二个是连接器,第三个是c语言编译器
汇编语言的编写:gedit,默认的gedit不会高亮显示AT&T汇编语言,我一会儿传一个脚本上来,是从国外网站上搬进来的,特别好用,支持AT&T i386高亮显示而且做的挺好看的,当然Eclipse也是个不错的选择,但是前期就没有必要使用了,等系统复杂了我再使用Eclipse
虚拟机:qemu,书上就是用的这个虚拟机,我之前一直都是vmware,不过看起来还是很好用的,apt-get install装上,具体怎么用现学现卖吧
好像写一个系统也就这些东西,似乎很简单的样子,写文章总喜欢感谢一下GNU,在这里再感谢一下这帮伙计。
二、创建今天用的文件
开始了,第一步,在文件夹里创建好今天要用的文件,先说一嘴,操作系统的大致启动步骤,首先CPU上电,内部电路控制CPU去0xFFFFFFF0这个位置取指令,就是在这16个bytes中存着一个小程序,把BIOS加载到内存某个位置,然后jmp去启动BIOS,BIOS会将某种启动方式的启动程序加载到0x7c00处,比如说用U盘启动,它会把U盘最开始的512个字节加载到0x7c00处,然后这512个字节中就要我们自己写一个loader程序,把我们的系统加载到内存中并且启动起来,真复杂哈,不如arm处理器做的简洁。当然,如果作为一个Linux老司机,GRUB是必须的,GRUB会把操作系统加载到0x10000位置,然后启动。我们写的是基于bios启动的,所以,不关心GRUB了,我们的第一步当然就是把这个loader做出来。
创建今天用的文件:
loader.s:loader的汇编源程序
loader.lds:我习惯用lds指定link方式,当然不用也可以
Makefile:如果想每次都输入那么长的命令行的话,就把这个也省略了吧
1、先把次要工作做完,把Makefile的代码贴上来
run : loader.bin dd if=loader.bin of=loader.img bs=512 count=1 dd if=/dev/zero of=zero.img bs=1474048 count=1 conv=sync dd if=zero.img of=loader.img bs=512 seek=1 qemu-system-i386 -fda loader.img -boot aloader.bin : loader.o Makefile loader.lds ld -M --oformat binary -m elf_i386 -o loader.bin loader.o -T loader.ldsloader.o : loader.s Makefile as --32 loader.s -o loader.o clean : rm *.bin *.o *.img
说一下这么写是什么意思,因为我们要用gemu虚拟机,所以必须要创建一个镜像文件.img,我们按照书上来,选择用软盘启动,所以我们要创建一个含有我们程序的软盘镜像,linux下可以用dd命令创建镜像文件,第一个dd把生成的纯二进制文件(raw binary file)打包成了一个.img,其实就是复制过程,没有做任何改变,第二个dd我创建了一个空文件,它的大小是1474560-512,是除去loader程序的一个空的镜像文件,因为一个软盘的容量是1474560字节,我们就要创建一个这么大的文件来模拟软盘。第三个dd是把两个文件合并了,最后qemu加载软盘跑起来。
在这里说一下ld命令,ld是链接命令,编译和链接是两个过程,-M是生成位图文件,便于我们查看文件具体是怎么链接的,-oformat是指定生成文件格式,选择纯二进制binary,-m是制定机器语言指令集,这里是i386指令集,-o输出文件,-T指定链接文件,一会儿简单讲一下lds文件怎么做。
as命令是gcc编译器的汇编器,默认支持的是AT&T格式汇编,但是似乎也支持NASM格式,NASM们的福音,可以在选项里边指定格式,我因为长期使用gcc做arm,所以可能还是AT&T格式更习惯一些吧,当然30天自制操作系统用的是NASM格式,各取所需。
最后加了个clean
2、这个是lds文件,后边有时间我写一个这方面的文章,网上资料太少了,这么好用的文件
这个lds最基本了,就是把.text段放在了0x7c00位置处,跟ORG命令异曲同工
SECTIONS{ . = 0x7c00; .text : { *(.text) } .data : { *(.data) } .bss : { *(.bss) }}
3、开始汇编
.code16.global _start.section .text_start: jmp entry .byte 0x90 .ascii "HELLOIPL" .word 512 .byte 1 .word 1 .byte 2 .word 224 .word 2880 .byte 0xf0 .word 9 .word 18 .word 2 .long 0 .long 2880 .byte 0,0,0x29 .long 0xffffffff .ascii "HELLO-OS " .ascii "FAT12 " .fill 18entry:
这一大堆是软盘的头文件,软盘格式规定必须要有,最开始给留了2 byte,可以放一个跳转指令,跳转到了程序入口entry,然后我们在程序入口把磁盘的一部分复制到内存中。以后上传代码我的两个代码段中间一定会有重叠,比如这个地方重叠entry:方便一下大家联系。
entry: movl $0, %eax movl %eax, %ds movl %eax, %ss movl $0x7c00,%esp movl $0x0820,%eax movl %eax, %es movb $0, %ch #柱面0 movb $0, %dh #磁头0 movb $2, %cl #扇区2read: movb $0x02, %ah #读磁盘 movb $1, %al #读一个扇区 movw $0, %bx movb $0, %dl #A驱动器 int $0x13 #读磁盘 movl %es, %eax add $0x0020,%eax movl %eax, %es inc %cl cmp $18, %cl jbe read movb $1, %cl inc %dh cmp $1, %dh jbe read movb $0, %dh inc %ch cmp $9, %ch jbe read jmp 0x8200marker1: .fill 0x1fe-(marker1-_start) .byte 0x55, 0xaa
不像书里写的那么复杂,我就把复制过程简化了,不考虑出现读盘错误的情况,毕竟在虚拟机里做是不可能出错的,以后完善的时候再考虑,复制过程调用了bios中断int13,可以操作各种存储设备,bios中断向量表网上一查一大堆,自己下载一个对照着指令就会用了,注意是bios!!!不是windows中断向量表,也不是linux。我把软盘前18*2*10*512字节的东西复制到了0x8200的位置处,之所以movl $0x0820, %eax的原因是前边有512字节的东西被bios加载到了0x7c00位置,就不读这一部分了,把前边512字节空出来,这样地址看起来比较完整,毕竟你也不缺那512字节,现在电脑动不动就是16G内存。可能还有小伙伴不懂为什么是0x0820而不是0x8200,因为我们赋值的是ES段,ESx16+BX才是最终地址,不要忘记这是段寄存器。
最后marker1位置处填充了一大堆0,留下最后的两个字节,写入了0x55,0xaa。其实55AA是一段神器的代码,几乎所有的通信校验位,启动标志位都是55AA,英文又把55AA翻译成magic code,确实很神奇哈,为什么人类达成了这样一个共识呢,我们把55 和 AA分别换算成二进制01010101,10101010,哇塞!就是通过这样的一个交替出现的设置,使得信息校验可以获得最大的准确度,具体的要涉及到硬件啦,当个笑话看看。所以呢,只有当bios校验了软盘最开始的512字节的最后两位是55AA,bios才能确定这里边装了一个loader,如果你不把这两位设置为55AA,那即使你的软盘里装了系统,bios也不会加载的,硬盘也是同样的道理。所以,我们现在把软盘的前2*18*10*512的东西装到了内存0x8000处,并且我们最后把指令指针交给了0x8200地址处,我们只需要在这个位置放上我们的系统初始程序就可以了
三、整理文件
整理一下文件夹,在os文件夹里创建一个system文件夹和一个loader文件夹,把loader有关的东西放到loader里边,在system文件夹里再创建三个文件,system.s,system.lds,Makefile
四、编写system.s
我们要开始写系统啦
system.lds链接文件同loader,把初始地址. = 0x7c00改为. = 0x8200
Makefile:
system.bin : system.o Makefile system.lds ld -M --oformat binary -m elf_i386 -o system.bin system.o -T system.ldssystem.o : system.s Makefile as --32 system.s -o system.o clean : rm *.bin *.o *.img
等把makefile改成嵌套型,就好用多了,现将就一下
打开system.s,写一个最简单的程序,把命令行模式改成画图模式,屏幕就会变黑,我们就证明我们的“系统”启动了
.code16.global _start.section .text_start: movb $0x13, %al movb $0, %ah int $0x10final: hlt jmp final
就这么简单,int 10中断可以操作屏幕,具体的自己搜咯
make一下,生成了system.bin,拷贝到loader文件夹下面,我们改一下makefile
run : loader.bin dd if=loader.bin of=loader.img bs=512 count=1 dd if=system.bin of=system.img bs=1474048 count=1 conv=sync dd if=system.img of=loader.img bs=512 seek=1 qemu-system-i386 -fda loader.img -boot aloader.bin : loader.o Makefile loader.lds ld -M --oformat binary -m elf_i386 -o loader.bin loader.o -T loader.ldsloader.o : loader.s Makefile as --32 loader.s -o loader.o clean : rm *.bin *.o *.img
改成这个样子,意思是把loader.bin和system.bin接起来,生成了loader.img,这就是我们的虚拟磁盘,make一下,OH yeah!
什么都没有就是成功了,这里推荐几个软件
二进制编辑器,bless,直接apt-get就可以了
objdump,readelf,都是不可或缺的软件。
orandragon原创,转载请链接地址http://blog.csdn.net/cheng7606535/article/details/76038518谢谢咯
- 从零开始搭建环境编写操作系统 AT&T GCC (一)搭建环境和测试环境
- 从零开始搭建环境编写操作系统 AT&T GCC (五)显示鼠标和字符
- 从零开始搭建环境编写操作系统 AT&T GCC (六)中断设置和启用 IDT PIC
- 从零开始搭建环境编写操作系统 AT&T GCC (七)GDB调试和-monitor
- 从零开始搭建环境编写操作系统 AT&T GCC (八)使用键盘和滚轮鼠标
- 从零开始搭建环境编写操作系统 AT&T GCC (二)从实模式到保护模式
- 从零开始搭建环境编写操作系统 AT&T GCC (三)引入C语言
- 从零开始搭建环境编写操作系统 AT&T GCC (四)绘制界面
- 从零开始搭建环境编写操作系统 AT&T GCC (十)多任务
- 从零开始搭建环境编写操作系统 AT&T GCC (九)内存管理
- 【操作系统】环境--环境搭建
- maven的环境搭建与测试编写(一)
- 从零开始搭建Hadoop环境
- Android从零开始-环境搭建
- 从零开始搭建Java环境
- Spring学习笔记(一)环境搭建和测试开发环境
- Spring学习笔记(一)环境搭建和测试开发环境
- angularJs测试环境搭建(一)
- Importance Sampling in Reinforcement Learning
- 应用程序与Activity 3_1 Android应用程序
- 寻找数组中的第i小元素
- 数理逻辑1 -- 命题演算6
- Mybatis错误(一)Exception in thread "main" org.apache.ibatis.exceptions.PersistenceException:
- 从零开始搭建环境编写操作系统 AT&T GCC (一)搭建环境和测试环境
- 子类的构造方法必须继承父类的构造方法
- POJ 3268 Silver Cow Party 最短路—dijkstra算法的优化。
- 羊皮卷之四
- POJ
- pyCharm最新2017激活码
- Linux内存模型
- Keepalived 的安装和配置
- JS事件