30天自制OS笔记:2 汇编语言学习与Makefile入门

进一步提高代码的高级程度,在之前的代码基础上修改,所以先拷贝再重命名为helloos.nas:

感觉还是添加个git比较方便,等helloos3完成后添加个git,这样可以保留历史,而不用每次都被覆盖了。

---------------------------------

先回顾下昨天的程序结构:

只有显示部分,昨天看懂了,继续2016年9月7日18:37:10,说实话那个

因为只能提醒很麻烦,所以取消notepad++自动补全:

?
?

下面把对代码的注释添加上:

寄存器:

?
?

X表示扩展的意思extend

可以看到,一共8个寄存器,共16个字节

段寄存器:

内存:超大规模的存储单元"住宅区"。

关键字:BYTE WORD DWORD

内存存储单元的单位是1个字节,注意了!

SI 是源变址寄存器的意思啊,就是source index的意思啊

可以用来指定内存地址的寄存器:BX\BP\SI\DI

BP指的是基址指针寄存器

为什么有的东西不能用呢?因为:

MOV BX, DX

MOV AL, BYTE [BX]

?
?

可以把中断理解为一种外部GOTO,我们知道GOTO随便跳,但再怎么跳还是在程序自己看得到的空间里面。

而BIOS程序则在另外一个空间里面,如果你想到那个空间,你可以发送中断,但是本质而言中断无非是一种特殊的GOTO而已罢了。

http://community.osdev.info/?(AT)BIOS 到这个页面可以搜索中断相关的东西,不懂日文没有关系,可以到百度翻译主页下载个网页翻译插件,目前看到最方便的就是这个插件了。

?
?

继续

操作显卡(函数放在BIOS服务集里面也就是函数集合)--》

本质上和操作其他硬件设备是一样的--显卡就是一个对象--》

对象就是数据结构(比如结构体套结构体)--》

操作显卡就是操作数据结构--也就是函数--》

要进入实模式RM里面调用

在上面那个网站上弄了半天,没搜到,直接在谷歌上搜了, http://wiki.osdev.org/BIOS 搜到这个页面:可以理解INT的含义啊。

HLT (x86 instruction)的时候,CPU做什么工作啊!为什么可以省电???难道CPU不工作了吗???和死循环有什么区别???

中断:设备发给CPU(中断驱动)的信号。设备什么时候发呢?比如定时器到了,就向早晨闹钟设备给你大脑发送信号一样。

CPU进入浅睡眠状态,先这么理解着吧,不然这书又要中断了,有时间看下这篇What Does an Idle CPU Do?

【内存分布】

Memory Map (x86)

代码理解完了,run一下看看:

没反应,对了先编译:

失败,估计汇编代码错了:哪里错了?

这样改了之后还是错:直接对比二进制看看哪里不一样吧?

BZ.exe可以比较多个二进制文件:

?
?

右边是可以运行的软盘映像二进制,可以看到0x01fe(510)-0x01ff(511)应该填55AA,因为:
?

?
?

但是根据我的汇编代码啊,根本不可能执行 DB 0X55, 0XAA了:

所以,进入到更高级的汇编代码部分,再也不想昨天只有DB/DW/DD/RESB这四种变相二进制填充指令了,所以必须有新的手段来建立启动区(启动区也是有文件系统的,这样BIOS才能识别吧,我猜的!)

【添加GIT】

以tolset目录作为git目录:

等之后确保Git使用没问题后,会上传到Github算做个备份吧,到时再弄。

为步骤helloos4做准备,操作系统是从无到有,一点点添加新功能,一点点测试通过的,所以helloos-n就对应着每个开发阶段,为了体现项目的演变,直接在前一个阶段的hellos3的目录上做修改,把helloos3重名为helloos4,表示进入helloso4阶段。

  1. helloos.nas的后半部分截掉(因为已经引入了GIT,所以再也不用每次都复制重命名了),启动区只要512字节;

  2. asm.bat-->ipl.bin 顺便输出ipl.lst反汇编文件,之前第二天的所谓汇编代码汇编后本质上就是个整个磁盘的二进制所谓机器码;
  3. 增加 makeimg.bat 以ipl.bin为基础,制作磁盘映像文件。
  4. 把其他不需要的删了(因为有GIT,可以恢复之前的版本,就又把删的找回来了,所以可以删了,清爽)

  5. 最后只要启动!cons 输入asm编译--》makeimg制作系统光盘--》run开机启动,这样一来比重装系统牛逼多了,因为系统也自己做的,然后光盘也自己做的,你可以多做几张光盘拿出去卖!

?
?

【制作启动区】

IPL

?
?

【Makefile入门】

Linux里用Makefile比较多,没想到windows下也能愉快地用这个,看来思维又局限到Linux下了。

看到:

它是说之前的程序是对的,我还以为不对呢!

那就用Git退回去吧,要退回去要先提交当前的状态,否则退不回去:

?
?

好的退回去了:重新打开helloos.nas,检查了发现一个大错误ox7coo应该是0x7c00

?
?

对比了一下生成的二进制镜像:

可以发现我生成的是大端格式,作者的是小端格式,不知道什么原因:

反正还是错了:

对照作者提供的程序修改下:

真是奇了怪了:我修改了和作者一样,但是编译后的55AA位置却不在0x1fe那个地方:

而是提前了,但是,BIOS是靠检测这个识别这个512字节的,然后确认这个是启动区,然后从头开始执行,然后是一条跳转JMP entry,跳到真正程序的地方。对比发现我第二个字节就错了:

看了0x4e应该是个南哥跳转指令了,那么肯定是我中途文件系统那块地方错了:

修改了之后,对比二进制文件,4e这次对了,但是55aa还是错了:

这是怎么回事?幸好有参考代码,对比了下发现了问题:

真是个大坑,原来:

?
?

好了,修改后终于好了:

总结下,之前程序总共错了三个地方:

  1. 0x7c00 把其中的0全部写成了字母o;
  2. 没有理解ORG代码的含义,没有理解原来机器码的含义;
  3. 没有理解地址偏移意味着所以地址编译器特殊处理;
  4. 好像本来也是小端字节存储的啊。

重新提交一下,不过现在版本有些混乱啊:

这里主要用到git rebase命令,《Git小书》小篇幅把这个简单用法讲清楚了。

这里说下一些命令的用法吧:

  1. 仓库--暂存区--工作区:如果此时工作区有一个文件发生了修改,如果你不想要这个修改,可以

    git checkout filename

  2. 切换到之前的某个版本 git checkout 版本ID
  3. 好的,如果你切换到之前的某个版本,然后修改了文件,然后再次git commit,此时就多出一个无名分支:如何为这个分支创建一个名称呢:操作如下命令 git checkout -b <new-branch-name>
  4. 普通删除分支 git branch -d test
  5. 强制删除分支 git branch -D test
  6. 记得在做分支操作的时候保证git staus没有提示有更改的文件

?
?

1<--2<--4<--5<--master

|

3<--6<--test

如果你要把3<--6插入到2和4之间,也就是要变成:

1<--2<--3<--6<--4<--5这个样子,做法是先切换到2<--3<--6这个分支,然后操作 git rebase master意思是把当前分支test衍合到master分支上,最终得到:

看下git操作历史:

推送到github备份下,推送就用图形界面吧,下载SourceTree软件吧,因为Github客户端总是下载失败:

  1. 初次安装后:

  2. 登录后,然后可以跳过克隆步骤;
  3. 它要求添加PPK格式秘钥,暂时不知道是什么意思,因为Github没有要求这个。

    你可以点击YES看下,要PPK,不懂,暂时选择NO吧,卡住的时候再回头即可。

  4. 打开那个git目录即可:

    选择文件夹之后就进入了仓库界面,还是很直观的:

  5. 然后就是怎么同步到Github了。首先到Github上新建个空仓库:30_OS_tolset
  6. 推送到远程仓库,命令行可以这么操作

    git remote add origin https://github.com/study-note/30_OS_tolset.git

    git push -u origin master

    这里是图形界面操作方式:

    首先是添加远程仓库,类似git remote add origin https:..git的功能:

    选择菜单:

    输入如下,和git remote add后填充的一样:

  7. 添加完远程仓库,现在就是推送了,类似git push -u origin master

    因为test1分支没用了,所以先删除:

    好了,现在推送master分支就可以了(注意你可以选择推送指定的分支,也就是推送是以分支为单位的):

    点击推送图形按钮即可:

    会再次提示你输入用户名和密码,输入即可。

    这个等待稍微有点慢...耐心等待它pushing完成...

    好了,完成!到项目主页上看下效果:成功推送,网站主要是方便分布合作、在线集成的、备份之类。

  8. 到此Git就完成了,其他项目都是都是类似的操作步骤。

    ?
    ?

【好了,刚才中断去处理错误了,回到Makefile入门】

这部分稍微有点乱,我是先看完了然后回头做个笔记,不过这段关于Makefile功能的解释真的很棒。

MOV BX, DX

MOV AL, BYTE [BX] AX\CX\DX\SP不能用来指定内存地址,BX\BP\SI\DI可以用寄存器来指定内存地址

----------------------------------------

我们的源文件是ipl.nas(把helloos.nas重名为ipl.nas,因为之前是生成整个映像,现在这个文件只生成ipl),因为之前我们为了生成整个软盘镜像,所以在源码中加入了启动区外代码,目的就是为了让汇编器帮助我们填充512字节之外的内容:里面填充的一些个别特殊的字符不懂是啥用,估计是软盘这么规定的吧,后面再说吧。

现在把这部分删掉,也就是把我们的代码编译器成512字节就好了。

注意:nask.exe既可以直接编译生成.img,也可以生成中间文件.bin,然后再生成.img文件。

----------------------------------------

接着编写Makefile文件,目的是生成.bin,然后再生成.img

解释:

把tolset/z_new_w/make.bat/拷贝到当前目录:

运行icons_nt.bat

输入 make ipl.bin 成功执行

书上加了个选项-r,我不太清楚是干嘛用的,因为好像没区别嘛,具体见这个网页GNU make: Options Summary

先来看下反汇编的结果ipl.lst:

接着查看ipl.bin的二进制格式,这个二进制格式看到的就应该是上面反汇编的那个机器码:

给Notepad++安装HEX-Editor插件

查看ipl.bin文件,可以看到确实正好是512个字节的二进制:

make 默认生成第一目标

------------------------------------------

再生成img看看: make -r helloos.img

生成成功:

Makefile是很智能的,它会遍历生成,如果你直接输入make -r helloos.img会中途生成helloos.bin

来试一下:

首先删除生成的东西:

然后输入 make -r helloos.img

可以看到确实如此啊。

如果我们重复执行 make -r helloos.img,因为make.exe自动检测到已经生成了,而且,helloos.img的依赖文件没有发生修改,这个是很智能的一件事:实验一下,确实如此

我们把输出显示改一下,看看:

我们不需要删除生成的文件,因为make新生成的文件回覆盖原来的:

成功了!

但是每次都要输入这么一个长命令实在麻烦,批处理其实是个偷懒的工具:

运行一下看看:

注意:纯bat批处理的目录分隔符是\(正好和转移字符冲突\),而Ubuntu里面都是/,改成:

这样就好了:

至此,生成一个提交,接下来进入helloos5阶段:

可视化看看分支变化:

?
?

----------------------------------------Makefile实在是高明啊

make可以智能处理目标的依赖关系

那么还能做成什么呢?如果我们把生成目标变成一个没有依赖的虚拟目标文件,它就会直接执行下面的命令了:
?

好了,Makefile用处,bat皆亡,makeimg.bat可以歇菜了!

我们再把文件里面的其他bat全部用Makefile实现:

bat一篇哀嚎啊!

就好比有了智能机器人,工厂失业一片啊。

注意了bat脚本不能在Git shell里面执行,要在CMD里面执行:

如何在特定目录下启动CMD呢?按住 shift,然后右键,看看效果:

?
?

出错了,到网上搜到一个答案:Copy a file using a makefile at runtime

直接运行copy没有任何问题,但是放到make里面,win7系统版本出问题了,改成:

xcopy /y

在DOS里 "\"是目录分隔符 目录和子目录之间的分隔作用

"/"参数符 这个符号后面DOS全部认为是参数

此时在Git Shell里面也可以运行了:

这次就好了:

成功

------------------------------------------

再增强一下Makefile的功能:

  1. 添加make clean删除中间文件,但不删除img文件

    测试:

  2. 添加make src_only,把源程序以外的文件全部删除干净,也就是img文件了,包含了make clean

    测试:

    出错,添加 -f 参数:解决方案参考Delete files in directory without erroring if it‘s already empty

    测试:

    测试通过!

  3. 增加make命令的默认动作,当执行不带参数的make时,就相当于执行"make img"命令(默认动作写在Makefile的最前头

    测试:

    测试通过!

最后把目录清理一下--提交--推送--完成第二天的任务:

第2天结束:2016年9月8日15:23:26

时间: 2024-09-29 21:51:39

30天自制OS笔记:2 汇编语言学习与Makefile入门的相关文章

汇编语言学习与Makefile入门

继续开发 ; hello-os ; TAB=4 ORG 0x7c00 ; 指明程序的装载地址 ; 以下的记述用于标准FAT12格式的软盘 JMP entry DB 0x90 DB "HELLOIPL" ; 启动区的名称 DW 512 ; 每个扇区(sector)的大小 DB 1 ; 簇(cluster)的大小 DW 1 ; FAT的起始位置 DB 2 ; FAT的个数 DW 224 ; 根目录的大小 DW 2880 ; 该磁盘的大小 DB 0xf0 ; 磁盘的种类 DW 9 ; FAT

30天自制操作系统笔记(第四天)

这一节讲的最出彩的地方是c语言的地址. 而要理清c语言地址,又必须追根溯源,看看汇编里内存地址的使用. MOV AL,0X15 MOV [1024],AL MOV BYTE[1024],0X15 这两种指令效果相同,都是在这个内存地址里存入一个数据,而学过汇编的我们知道,直接往内存某地址存入数据时,要说明填入的数据大小,或者说数据类型,不然机器不知道怎么填入该数据,到底是按照8位填入,还是十六位填入.因此,这个byte必不可少,而前面的指令,由于AL已经明确了是八位,因此不用说明. 好了,接下来

读书笔记--30天自制操作系统 目录

1.着手开发前 开发步骤 1.编写源代码 2.用编译器编译 3.生成软盘映像 4.将映像写入磁盘,做成启动盘. 2.计算机结构到汇编程序入门3.汇编语言学习与Makefile入门4.进入32位模式并导入C语言5.C语言与画面显示的练习6.结构体.文字显示与GDT/IDT初始化7.分割编译与中断处理8.FIFO与鼠标控制9.鼠标控制与32位模式切换10.内存管理11.叠加处理12.制作窗口13.定时器114.定时器215.高分辨率及键盘输入16.多任务117.多任务218.命令行窗口19.dir命

《30天自制操作系统》——虚拟机使用

<30天自制操作系统>是一本学习操作系统的好教材,它教我们怎么从建立引导区开始,从零实现一个操作系统.但是,实现书中例子的时候,我们需要不断将我们写好的操作系统代码写入软盘并且还要不断重启电脑来试验我们的代码,大家一定感到很头疼吧. 与其不停的重启,不如使用模拟器,向大家推荐一款模拟器qemu,它是由Fabrice Bellard编写,功能非常强大.那么下面我就来教大家使用qemu运行书中自制操作系统的方法吧. 一.安装qemu 我使用的是苹果笔记本,苹果有一个非常好用的程序管理工具叫brew

《30天自制操作系统》笔记(01)——hello bitzhuwei’s OS!

<30天自制操作系统>笔记(01)--hello bitzhuwei's OS! 最初的OS代码 1 ; hello-os 2 ; TAB=4 3 4 ORG 0x7c00 ; 指明程序的装载地址 5 6 ; 以下这段是标准FAT32格式软盘专用的代码 7 8 JMP entry 9 DB 0x90 10 DB "HELLOIPL" ; freeparam 启动区的名称可以是任意的字符串(8字节) 11 DW 512 ; 每个扇区(sector)的大小(必须为512字节)

《30天自制操作系统》学习笔记-第1天

为了加深对操作系统的理解,我决定照着<30天自制操作系统>这本书实践一下.项目的github链接是https://github.com/YatesXu/YatesOSASK/ 关于十六进制编辑器 第一个问题就是书中给的十六进制编辑器是日文的,在我的电脑上打开之后是一片乱码,于是我比较之后选用了这个十六进制编辑器wxMEdit,链接是https://wxmedit.github.io/. 另外,visual studio也可以,但是express版不能用,所以还是选用免费开源的软件吧(笑) (伪

《30天自制操作系统》笔记(03)——使用Vmware

<30天自制操作系统>笔记(03)--使用Vmware 进度回顾 在上一篇,实现了用IPL加载OS程序到内存,然后JMP到OS程序这一功能:并且总结出下一步的OS开发结构.但是遇到了真机测试和U盘启动的一些问题.本篇就来解决之. 遇到的问题 物理机测试 简单来说,把软盘(U盘)做成启动盘后,自然想要用来启动物理机器.毕竟这才是真正的测试.(用QEMU总没多大的成就感)但物理机测试的麻烦在于太慢了,每次都要关掉Windows,重启,测试,然后再重启Windows.而且还没办法截图. 而用Vmwa

《30天自制操作系统》笔记(02)——导入C语言

<30天自制操作系统>笔记(02)--导入C语言 进度回顾 在上一篇,记录了计算机开机时加载IPL程序(initial program loader,一个nas汇编程序)的情况,包括IPL代码(helloos.nas).编译生成helloos.img文件.用虚拟机QEMU加载helloos.img.制作U盘启动盘和用物理机加载helloos.img. 计算机启动时会自动加载和执行IPL程序,但IPL程序只能占用512字节.若直接用IPL写OS,空间不够用.所以IPL程序一般用于将真正的OS程序

《30天自制操作系统》读书笔记(3) 引入C语言

这一次的学习相当曲折, 主要是因为粗心, Makefile里面的错误导致了文件生成出现各种奇奇怪怪的问题, 弄得心力交瘁, 因此制作过程还是尽量按着作者的路子来吧. 作者提供的源码的注释在中文系统下是乱码, 而且代码的分隔用了两个Tab, 在这里要处理一下: :%s/;.*//g 删除所有的注释; :%s/\t\t/\t 把两个Tab替换为一个Tab; 要让作者的nas文件和asm文件拥有相同的语法规则, 在_vimrc文件的最后一行添加 au BufNewFile,BufRead *.nas