从头写一个操作系统 04

in #esteem5 years ago (edited)

你可能需要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.asmboot_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载入了一对字符串与几个字节的数据,调用了printprint_hex 后进入死循环,如果前面的文章都读了,这里很容易理解。

Sort:  

继续支持码农!

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 published more than 50 posts. Your next target is to reach 60 posts.

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:

The Steem blockchain survived its first virus plague!
Vote for @Steemitboard as a witness to get one more award and increased upvotes!