从零开始搭建环境编写操作系统 AT&T GCC (一)搭建环境和测试环境

  又有闲时间了,一直没有在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 a

loader.bin : loader.o Makefile loader.lds
    ld -M --oformat binary -m elf_i386 -o loader.bin loader.o -T loader.lds

loader.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   18
entry:

  这一大堆是软盘的头文件,软盘格式规定必须要有,最开始给留了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 #扇区2

read:   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 0x8200
marker1:
    .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.lds

system.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 $0x10

final:
    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 a

loader.bin : loader.o Makefile loader.lds
    ld -M --oformat binary -m elf_i386 -o loader.bin loader.o -T loader.lds

loader.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!
从零开始搭建环境编写操作系统 AT&T GCC (一)搭建环境和测试环境_第1张图片
  什么都没有就是成功了,这里推荐几个软件
  二进制编辑器,bless,直接apt-get就可以了
  objdump,readelf,都是不可或缺的软件。
  orandragon原创,转载请链接地址http://blog.csdn.net/cheng7606535/article/details/76038518谢谢咯

你可能感兴趣的:(OranOS,操作系统,计算机,编辑器,编程,博客)