操作系统学习与实践5:操作系统C内核——调试工具printf

本文详细介绍了在操作系统C内核中如何从头实现调试工具printf。内容涵盖CDECL调用规则、printf函数的参数处理、调用栈原理以及手动编写打印字符的ASM函数。通过这篇文章,读者可以理解在实模式下混合使用C和汇编编程的技巧,以及动态参数函数的设计思路。

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

一、回顾及存在问题

       前面我们讲了, bootloader的作用有三个:一是收集系统状态信息;二是将设置系统状态,以满足操作系统运行要求;三是加载和执行操作系统(kernel)。

       我们已经完成了:

        1. 驻留内存的引导程序;

        2. 驻留在第1个引导扇区的bootloader编写,将内核程序加载到内存执行;

        3.  完成了由汇编转向C语言入口程序cstart_()地方(asm如何调用C,如何编译链接16位实模式下的C语言),现正式进入C语言世界!

       本节首先我们需要用C语言从头实现一个调试工具——printf。

二、:基本的函数调用过程分析

     1. CDECL 调用规则:https://en.wikipedia.org/wiki/X86_calling_conventions

        (1)基本规则

                         -参数:自右向左压入堆栈

                        -调用者(汇编语言)负责将参数从堆栈中取走

                        - 返回值:整数,指针是放在EAX中,浮点是STO

                        - 使用的寄存器:EAX,ECX,EDX由调用者保存原始值,函数调用结束,返回前恢复

                         自动在c语言函数名称前加一个“_”,转变为汇编函数名称。

         (2)CDECL汇编示例

                      asm调用c函数的实际代码执行情况(堆栈变化)

                     1)首先保存原来上下文,将参数、返回地址压入堆栈;   

             2)进入子函数(被调用函数),保存旧的堆栈结构地址,并将bp指向新的堆栈底 (mov bp, sp),到这里我们已经准备好执行被调用函数内部了。

                     3)   在被调用函数内部,因为bp不变,所以输入的参数使用[bp-n]代替,首先空出一块区域存放子函数的返回值  (sub sp,2; 用于存放lengthSq函数中的r临时变量)

        4)   子函数内部执行

           执行完将sp中的值修正为 r (mov [sp-2], ax)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值