裸机版HelloWorld

内核开发 置顶精帖
9 1579
LMOS LMOS 2018-03-13
积分:15

hello world程序绝对经典的让人落泪,这是很多人的第一个程序。这个程序在Brian Kernighan和Dennis M. Ritchie合著的《The C Programme Language》中使用而广泛流行。该程序也体现了两位作者心向世界的情怀。

我编程也是从hello world程序开始的,但是很多人写的hello world程序都需要库和操作系统的支持才能运行。今天我想来用C语言重新实现一个裸机版hello world程序,即不需要操作系统和库的支持。如果要为一段程序颁布一个图灵奖的话,我希望是C语言版的hello world!

首先看看实现裸机版的hello world程序所需要的工具:

1.LINUX操作系统

2.编译器:GCC、LD、nasm

3.文件编辑器

4.Make

5.GRUB引导器(安装LINUX时已经自带了)

下面我们从上向下完成hello world程序,首先来写好main函数,如下:

深度截图_选择区域_20171229134325

是不是很熟悉,这样的程序,我想很多人闭着眼一通盲码,都可以正确无误

好了,上面的代码依然是调用了printf函数输出“hello world!”字符串的,由于这裸机版的程序,所以不能调用库中的printf函数,而是要自己亲自实现该函数。下面就去实现一个最简单的printf函数。如下: 

深度截图_选择区域_20171229134507

确实够简单了,没有像通常的printf函数处理多个参数,也没有对参数进行格式化处理,而是调用了_strwrite函数,_strwrite函数才是输出字符串的核心函数,它把字符串的每个字符,依次写入以0xb8000为开始地址的内存空间,这个内存空间默认映射是显卡的显存,并且我们知道计算机启动时显卡默认工作在字符模式下。对应于屏幕是每行80个字符,一共有25行。

可是有了这些代码就可以了吗,当然不行,因为是裸机,所以在调用C函数之前,还要初始化栈和CPU的一些寄存器,更为关键的是我们的程序要被GRUB载,而这些动作用C语言又无法实现,这时我们的大汇编语言就该上场了,发挥它神奇的作用了,下面来用汇编语言写一段代码,如下:

深度截图_选择区域_20171229133915

深度截图_选择区域_20171229134128

这段代码不必多说,上面的注释已经写的很好了,汇编程序代码也写好了,最后的工作就是编译链接程序了,编译还好说,但是链接就不能用通常链接应用程序的方法了,因为这时裸机程序,所以我们得写个链接脚本来控制链接过程,脚本和源代码都在:

https://github.com/lmnos/PmHelloWorld.git

可以自行git clone 然后make一下,就自动编译链接好了

安装测试,在linux系统下则非常方便,因为linux系统已经安装好了GRUB2,默认情况下,只要把pmhello.bin文件复制到linux系统的/boot/目录下,同时修改/boot/grub/目录下的grub.cfg文件。如下图所示:

深度截图_选择区域_20171229134854

重启计算机就可以看到PmHelloWorld启动选项了…… 




  • yason.li yason.li
    2018-03-13

    每当老大发精华帖的时候,我一定要抢一楼啦~

    5 回复
  • 板凳是我的

    1 回复
  • safeoy safeoy
    2018-03-13

    学习了

    1 回复
  • Jacklli Jacklli
    2018-03-13

    徒手hello world!

    1 回复
  • chengang chengang
    2018-03-13

    了解学习。。。


    对了p_strdst+=2   是Unicode字符的原因吗?

    1 回复
  • EricJiang EricJiang
    2018-03-14

    留名

    1 回复
  • LMOS LMOS
    2018-03-14

    不是,这是因为显存 还有一个字节 是控制 显示属性的,所以要跳过

    chengang:

    了解学习。。。


    对了p_strdst+=2   是Unicode字符的原因吗?

    0 回复
  • 冯兆亮 冯兆亮
    2018-03-20

    学习了~~

    0 回复
  • a133333 a133333
    2018-04-07

    写个链接脚本来控制链接过程


    0 回复