从头写一个操作系统 04
你可能需要google这几个知识点: control structures, function calling, strings
目标: 使用汇编编写基本的逻辑(循环、函数)
越来越接近目标中的启动引导区了。
在https://github.com/cfenollosa/os-tutorial中的lesson 7中,我们会从硬盘中读取引导数据,而后便进入启动内核的步骤。不过目前我们还需要做些必要的准备:练习写一些控制结构、函数调用,读取字符串的代码。
Strings
像写入字节一样写入字符串,用空字节(像C语言一样)标识字符串的结尾。
mystring:
db 'Hello, World', 0
注意,被引号包围的文字会被编译器转义为ASCII码('0' == 0x30
),而0就是0x00
,代表空字节。
Control structures
我们之前使用过jmp $
制造一个无限循环。
汇编语言的跳转位置由伪指令标识,例如:
cmp ax, 4 ; if ax = 4
je ax_is_four ; do something (by jumping to that label)
jmp else ; else, do another thing
jmp endif ; finally, resume the normal flow
ax_is_four:
.....
jmp endif
else:
.....
jmp endif ; not actually necessary but printed here for completeness
endif:
用高级语言的语法思考一下上面程序的逻辑,再将它们用汇编语言的方式表达出来。
有很多判断jmp
的方式,比如if equal,if less than。有时并不是很直观,但google一下总归会很快明白。
Calling functions
你可能会认为调用函数就是跳转到对应label。
但处理参数是个棘手的事,需要两步:
1.程序员需要确定传递信息的的那个寄存器或者内存地址。
2.编写代码使程序通用并且没有副作用
步骤一简单,我们就让al
(实际上使ax
)来传递参数吧。
mov al, 'X'
jmp print
endprint:
...
print:
mov ah, 0x0e ; tty code
int 0x10 ; I assume that 'al' already has the character
jmp endprint ; this label is also pre-agreed
代码流程简单直接。print
函数最后总会跳转到endprint
,但是如果别的函数需要调用它呢?可以看出来,这段代码无法复用。
正确的解决方案会改进两个地方:
返回的地址是调用前便保存好的。
保存所有寄存器状态,使得子函数可以更改它们的状态。
CPU提供了保存返回地址的功能,不需要用jmp
跳转到子例程,只需要用call
来调用、ret
来返回。
有一组特殊的命令可以使用堆栈保存或恢复寄存器的状态:pusha
可以自动保存所有寄存器状态,popa
用于最终恢复寄存器调用函数前的状态,
Including external files
我假设你是一个程序员,所以不再赘述程序源码组织的重要性。
语法如下:
%include "file.asm"
Printing hex values
下一节课,我们会从磁盘中读取数据,所以需要一个确认读取数据是否正确的途径,boot_sect_print_hex.asm
与boot_sect_print.asm
配合,可以打印输入为16进制数字的文本,而不是ASCII码。例如输入0X12FE ,输出为'0X12FE',
虽然看起来一样,但后者的实际ASCII码对应的16进制数为 '0'=0x30 'X'=0x58 '1'=0x31 '2'=0x32 'F'=0x46 'E'=0x45
Code!
让我们回到代码,文件boot_sect_print.asm
是被main文件 通过%include
包含进来的子文件。它用一个循环将字节打印到屏幕上,而后通过print_nl
函数打印换行符\n
,\n
其实有两个字节,换行符oX0A
和回车0X0D
,试一试如果删掉回车会有什么影响!
如上所属,boot_sect_print_hex.asm
可以打印
主文件 boot_sect_main.asm
载入了一对字符串与几个字节的数据,调用了print
与 print_hex
后进入死循环,如果前面的文章都读了,这里很容易理解。
继续支持码农!
Posted using Partiko Android
哈哈哈,已经无法表达我的感激了!
🙂 加油
Posted using Partiko Android
一定,很久以前就想写这个系列,现在的每一篇文章最后都会在我的开源仓库里作为一个章节的README,思路是完整的,现在我的目标就是克服懒惰
我是一名过气码农。我最后接触的就是 C ,连+符号都还没有。Assembly 对我来说还是挺亲切的。至于懒惰,是因为没有读者。继续写吧,有空给别人留言点赞一下。多抱几个大腿。收益就是动力,很快你就不懒了。🤣
Posted using Partiko Android
没想到还是同道!那么多语言里我最喜欢的汇编语言,在汇编语言里没有乱七八糟的工具和标准库,告诉计算机什么就是什么,很多知识被抽象之后就变得晦涩了。
懒惰的原因你说对了,上一次没有坚持写下去就是因为看重收益,不过这次心态很好,一点一滴的写下去,不管收益好不好,都是自己要做的一件事。还有,steem有一些别人没有意识到的价值,就像咱俩的聊天,在过去是不可能的,steem的ip被封锁后,由于去中心化的服务器设施,才让我有机会继续发言,如果不是这些服务器,大部分国人与steem将被彻底切断。不经意间,区块链竟然在我的生活里,以这样的背景落地了,多有意思
Thanks for using eSteem!
Your post has been voted as a part of eSteem encouragement program. Keep up the good work! Install Android, iOS Mobile app or Windows, Mac, Linux Surfer app, if you haven't already!
Learn more: https://esteem.app
Join our discord: https://discord.gg/8eHupPq
Congratulations @geyu! You have completed the following achievement on the Steem blockchain and have been rewarded with new badge(s) :
You can view your badges on your Steem Board and compare to others on the Steem Ranking
If you no longer want to receive notifications, reply to this comment with the word
STOP
To support your work, I also upvoted your post!
Do not miss the last post from @steemitboard:
Vote for @Steemitboard as a witness to get one more award and increased upvotes!