30天自制操作系统day21

本文详细介绍了在自制操作系统中如何用C语言编写应用程序,涉及到将C语言调用转换为汇编中断,以及保护操作系统的措施,如分配不同数据段避免内存冲突,并实现对异常的支持,包括处理0x0d中断来防止应用程序破坏操作系统。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

用C语言编写应用程序

要调用API,需要将参数放到寄存器中然后中断,C语言中没有这样的指令,所以写一个汇编函数:

_api_putchar:   ; void api_putchar(int c);
        MOV     EDX,1
        MOV     AL,[ESP+4]      ; c
        INT     0x40
        RET

将函数参数放到AL中,然后中断。在C语言中只需要 api_putchar() 就可以了。
但是编译出的.hrb程序不能运行,因为它没有可执行文件的头。将.hrb程序开头6个字节替换成 E8 16 00 00 00 CB ,相当于:

[BITS 32]
        CALL    0x1b
        RETF

0x1b是程序main函数开头的位置。用RETF是因为程序是从操作系统跳转过来的。

保护操作系统

现在应用程序可以向任意内存地址写入数据,这会破坏操作系统。
之前只为应用程序分配了代码段(CS),数据段DS/SS和操作系统相同。需要为数据段也分配不同的空间。
在start_app()函数中,从参数中获得应用程序的EIP,CS,ESP,DS/SS。EIP是程序起始地址,一般为0,CS是代码段的段号,ESP是栈起始地址,一般等于栈大小值。DS和SS相同,是数据段的段号。将寄存器中的ESP,DS/SS替换成刚才的值,然后将EIP,CS push到栈上,使用 CALL FAR [ESP] 跳转到这个位置。应用程序返回后,恢复操作系统的CS,ESP,DS/SS并返回。

使用API函数时,由于API函数是写在操作系统里的,也需要切换上述寄存器。在asm_hrb_api()中,一方面需要保存寄存器,另一方面需要将寄存器PUSH作为hrb_api()的参数。保存的寄存器在应用程序的栈上,而作为参数的寄存器复制到操作系统的栈上。

同理,中断函数也在操作系统中。当从应用程序中断时,需要切换DS,SS,ESP寄存器。

对异常的支持

当应用程序试图破坏操作系统时(访问操作系统的内存空间),会产生0x0d中断。注册一个中断函数处理这个异常。
在中断函数中,强制结束程序的方法是将ESP恢复到start_app()时的位置,然后RET直接回到cmd_app()。

但是如果应用程序将段修改为操作系统的段,依然可以改写操作系统内存空间的数据。我们可以禁止应用程序向DS存入操作系统段号。
在cmd_app()中,分配应用程序的数据段和代码段时,权限加上0x60,表示应用程序用。
这样的话,操作系统又不能CALL应用程序了。可以使用RETF。把EIP和CS PUSH到栈上,然后使用RETF,效果和CALL FAR 一样。
在应用程序里也是不能用RETF了。

其实这章后面完全没看懂。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值