|| 版权声明:本文为博主原创文章,未经博主允许不得转载。

  一、前言

    今天起开始分享关于操作系统的相关知识,本人也是菜鸟一个,正处于学习阶段,这整个操作系统篇也是我边学习边总结的一些结果,希望能给正在学习或者有意向学习操作系统的童鞋带来帮助。

    二、有关知识
    在进入代码之前,先给大家普及一些硬件知识,如果你已经具备了这方面的知识,可以直接略过这部份。
    1.计算机怎么启动操作系统的?
    首先,我们思考一个问题,为什么一个硬盘安装系统之后打开计算机电源之后就能正常加载启动呢?这看起来似乎很智能,似乎计算机像活的一样会自动去硬盘中找系统代码并自行加载。其实不然,在计算机的世界里一切也都是离不开规则的。而基于这些硬件所定的规则或者协议,我们将启动代码放到协议规定的地方,这时候启动就会加载这部分代码。听起来好像有点乱,我们继续看。
    2.主引导扇区
    很多安装过系统的童鞋都应该知道引导盘这个东西,就是在我们启动电脑的时候可以通过bios来设定是通过U盘启动还是通过硬盘启动。对于硬盘来说,硬盘的第一个扇区是 0 面 0 道 1 扇区,或者说是 0 头 0 柱 1 扇区,这个扇区称为主引导扇区。如果计算机的设置是从硬盘启动,那么, ROM-BIOS 将读取硬盘主引导扇区的内容,将它加载到内存地址 0x0000:0x7c00 处(也就是物理地址 0x07C00),然后 jmp 跳到那里接着执行:
jmp 0x0000:0x7c00

  为什么偏偏是 0x7c00 这个地方?还不太清楚。反正当初定下这个方案的家伙已经被人说了很多坏话!!

  通常,主引导扇区的功能是继续从硬盘的其他部分读取更多的内容加以执行。像 Windows 这样的操作系统,就是采用这种接力的方法一步一步把自己运行起来的。

说到这里,我们可以想象,如果我们把自己编译好的程序写到主引导扇区,不也能够让处理器执行吗?    
其实这就是我们寻找的答案,这几乎是在不依赖操作系统的情况下,让我们的程序可以执行的唯一方法。但这里要注意可别拿自己的电脑乱试,系统一下就瘫痪了,我们可以通过虚拟机来进行我们的代码运行与调试。
  三、配置
  1.nasm
    首先安装nasm,方便编译我们的代码,为了大家方便,本文后面会附上相关的下载地址。
    安装过程是直接安装,一直next:
  
  
  安装完成之后,我们可以启动nasm的shell,通过该shell进行相关编译工作。
  2.bochs
    该软件可用于创建硬盘或软盘,同时也可模拟计算机启动,可以加载我们写好的启动盘。
 
  点击I Agree进入下面的界面:
 
  这个界面,大家看自己的需求选择,然后点击next:
 
  

  这里DLX Linux Demo是默认没选上的,安装Bochs时不妨选中“DLX Linux Demo”,便可直接参考它的配置文件。
  继续next:
 
选择好安装位置,install就行了。
    3.dd
    该工具用于将我们编译后的机器码写入到启动扇区中。我这里用的是dd-0.6beta3,将附件下载后解压,拿到里面的exe文件,在cmd下cd到该目录就可以使用dd命令进行写入操作。
  四、程序
    说了这么多,还没见到代码,下面我们就一段代码了实现字符串的显示,由于代码是用汇编写的,所以没有汇编基础的童鞋可能需要先看看汇编的语法。
废话不多说了,直接上代码:
 org 07c00h ;告诉计算机将代码加载到内存的07c00h
mov ax, cs
mov ds, ax ;初始化数据段ds
mov es, ax ;初始化附加段寄存器
call DispStr ;调用DispStr来显示字符串
jmp $ ;无限循环
DispStr:
mov ax, BootMessage ;将字符串地址传给寄存器ax
mov bp, ax ; 通过ES:BP来指向显示的字符串
mov cx, ; 表示字符串的长度
mov ax, 01301h ;10h的13号中断,此时通过AH=13传入,AL=,表示目标字符串仅仅包含字符,属性在BL中包含,移动光标
mov bx, 000ch ;BH表示视频区页数
mov dl, ;DL表示在第几列显示(0为第一列)
int 10h ;10H中断
ret
BootMessage: db "Hello,OS World!"
times -($-$$) db ;用times来创建字节0
dw 0xaa55 ;扇区结尾,写入引导程序标志位
  上面的代码注释比较清晰的解释了程序的意思,这里我们在详细分析一下。
  在前面我们讲到因为硬件设计的原因,在充电的时候,回去内存的07c00h处读取指令,因此,我们通过org 0700ch来讲程序加载到该地址。接着初始化了段寄存器,然后调用字符串的显示的代码部分从而将字符串显示在显示器上面。
  在DispStr中,相关寄存器的操作都是为了后面的10H中断做准备,int 10h这条指令的触发将会使得ES:BP所指向的字符串进行显示。
  显示完成后,原则上整个程序就结束了,但对处理器来说,它并不知道。对它来说,取指令、执行是永无止境的。程序有大小,执行无停息,它这么做的结果,就是会执行到后面非指令的数据上,然后……
  问题在于我们现在的确无事可做。为避免发生问题,源程序第 6 行,安排了一个无限循环:jmp $。其中$等同于标号,你可以把它看成是一个隐藏在当前行行首的标号。
     说到这里就只剩下最后两行代码了,其实这里也是可以算是一个协议来的。因为主引导扇区在系统启动过程中扮演着承上启下的角色,但并非是唯一的选择。如果硬盘的主引导扇区不可用,系统还有其他选择,比如可以从光盘和 U 盘启动。
     然而,如果不试试水的深浅就一个猛子扎下池塘,这并非一个明智之举。同样地,如果主引导扇区是无效的,上面并非是一些处理器可以识别的指令,而处理器又不加鉴别地执行了它, 其结果是陷入宕机状态,更不要提从其他设备启动了。
     为此,计算机的设计者们决定,一个有效的主引导扇区,其最后两个字节的数据必须是 0x55和 0xAA。否则,这个扇区里保存的就不是一些有意而为的数据。这就是最后一行代码的解释:dw 0xaa55。
  根据上面的说法,这里还要解决另外的一个问题,就是如何使这两个字节正好位于 512 字节的最后。前面的代码有多少个字节我们不知道,那是由 NASM 编译器计算和跟踪的。这时倒数第二行代码就起作用了,这里通过创建数值为0的字节来补充余下的空间,其中$$是 NASM编译器提供的另一个标记,代表当前汇编节(段)的起始汇编地址。
    到此,我们对于代码的分析完毕了。
  五、编译与运行
      这时候打开我们前面安装好的nasm shell,cd定位到我们的boot.asm的位置,然后执行nasm boot.asm -o boot.bin

  然后,我们通过bochs来创建一个软盘,通过软盘来做启动盘从而启动执行我们的程序。
  首先,打开bochs安装目录的bximage.exe文件

  下面是打开后的界面:

  然后输入1并回车,选择创建一个软盘或硬盘,进入下面的界面:

 

  这时候会询问要创建的类型是hd还是fd,我们输入fd回车,进入下面的界面:

这个提示是要我们选择要创建的盘符的大小,我们直接回车选择默认的1.44M就行了:

  到这里可以为创建的镜像输入名称,也可以用a.img作为默认名。回车后,这时会在bochs安装的目录下面多了一个a.img的文件,这个就是我们刚刚创建的镜像文件:

  到此,我们创建好了软盘,下面就是将程序写入到软盘的第一个扇区,这时,我们dd工具就派上用场了,我们启动命令行,cd到dd的根目录,然后执行写入的命令:
dd  if=boot.bin  of=a.img  bs=  count=  conv=notrunc

  注意这里我把编译好的boot.bin文件与镜像a.img跟dd放在同一目录,不是同一目录的同学请自行修改路径。

  执行完后,a.img就是我们要的启动盘了。
  六、运行
     运行的时候是肯定不能在真机上面运行的,这时就要用到虚拟机了,我用的是vm ware。
     首先,我们需要创建一个新的虚拟机,主要的步骤如下:

  

  选择自定义,单击下一步进入下一个界面:

  

  

  这里默认就可以了,直接单击下一步:

  

  这里选择稍后安装操作系统,下一步:

  

  这里选择其他,然后下一步:

  

  这里是处理器的配置,因为我们的程序都很简单,而不是玩游戏,所以选择最低配置就可以了:

  

  选择好内存,单击下一步:

  

  关于网络就随意选都行,反正我们暂时不会涉及网络方面的东西,单击下一步:

  

  IO控制器,直接默认就行,下一步:

  

  虚拟磁盘类型,选择IDE,单击下一步:

  

  创建磁盘,单击下一步:

  

  这里尽量选小一点的磁盘,因为我们用不上的,我们这里是通过软盘来启动的:

  

  选择磁盘文件的位置,然后单击下一步:

  

  单击完成,此时我们的虚拟机就创建好了。

     这个时候不要急于去启动它,因为我们还有将我们刚刚做好的启动盘配置进来,作为虚拟机的启动盘。下面我们继续通过截图来说明,这样会直观一些:

  

  这里我们选择图中红色圈住的地方,来我们刚刚创建好的虚拟机:

  

  选择添加,来添加我们刚刚制作好的软盘:

  

  选择软盘驱动器,单击下一步:

  

  选择使用软盘镜像,单击下一步:

  

  选择我们刚刚的a.img,并勾选启动时连接,单击完成。

  这时候我们的准备工作就结束了,可以启动虚拟机来看看我们的工作成果了:

  

  

  可以看到我们字符串Hello,OS World!显示在上面。
  这个时候,心细的同学可能有疑问了,为什么显示的字符串是红色的,为什么不是白色或者其他颜色呢?要显示其他颜色也是可以的,这其实是我们写在了程序里面的,这其实是有AL与BL寄存器来决定的。
  如果AL的BIT1为1,则BL表示显示属性。属性为:
  |BIT7|BIT6|BIT5|BIT4|BIT3|BIT2|BIT1|BIT0| BL
  BIT7:背景是否闪烁。0不闪烁,1闪烁
  BIT6~BIT4为背景色,分别为RGB,000为黑色,111为白色
  BIT3为1,则前景色加亮,为0则不加亮
  BIT2-BIT0为前景色,意义同背景色
  有兴趣的同学可以尝试修改代码运行试试,这里就不一一列举 了。
  七、总结
    回顾上面所讲的内容,我们主要讲解了以下几点的内容:
    1.如何免系统运行程序:由于硬件设计的原因,在计算机充电启动的时候会去内存的0x07c00h处读取指令,因此我们通过指令org 0x07c00h将代码加载到内存的该位置。
    2.计算机如何知道要我们制作的软盘就是启动盘呢?因为在软盘的第一扇区最后的两个字节是计算机识别启动盘的位置,我们通过将这两个字节设置成0xaa55,从而告诉计算机,该软盘就是启动盘。
    3.如何通过代码将字符串显示到显示器上?我们利用10H中断,该中断会去ES:BP所指向的内存地址读取内容并显示。
    4.显示是样式如何设定?将AX的低八位AL的BIT1设置为1,表示要显示的是字符串,而且样式包含在BL中,而在BL中我们设置的值为0x0c,也就是二进制的0000_1100,从上面 对BL的各个位的讲解,我们知道该内容是将字符串设置为红色。
    5.同时,我们也学会了利用bochs来制作镜像,另外bochs也可以用来调试,以后的文章也会用到,希望大家多多关注。
    6.通过dd工具将程序写入镜像。

  下面是本文中用到的相关工具的下载地址

操作系统篇-hello world(免系统运行程序)的更多相关文章

  1. Android中插件开发篇之----动态加载Activity(免安装运行程序)

    一.前言 又到周末了,时间过的很快,今天我们来看一下Android中插件开发篇的最后一篇文章的内容:动态加载Activity(免安装运行程序),在上一篇文章中说道了,如何动态加载资源(应用换肤原理解析 ...

  2. Android应用程序框架层和系统运行库层日志系统源代码分析

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6598703 在开发Android应用程序时,少 ...

  3. python介绍,计算机核心基础,与运行程序有关的三大核心硬件,操作系统

    python介绍,计算机核心基础,与运行程序有关的三大核心硬件,操作系统 引子 python是什么? 什么是编程语言?为何要有编程语言? 什么是编程?什么是程序?什么是进程?为何要编程? 计算机基础 ...

  4. 麒麟系统使用root权限运行程序

    最近在虚拟机里安装了个国产麒麟系统.(不知道麒麟系统的百度下.) ************************************************** 官方网址:http://www. ...

  5. 开发系统时候运行程序突然报出“WebDev.WebServer40.exe已停止工作”的错误

    已经解决,问题描述:在开发系统时候运行程序突然报出“WebDev.WebServer40.exe已停止工作”的错误,程序调试运行,发现程序在打开数据库时候报错,也就是Connection.Open() ...

  6. linux 系统shell运行程序不退出

    如果通过ssh远程连接到linux系统终端,在shell下执行程序.假如程序名称为app,且程序本身会一直执行不退出,程序执行需要参数文件paramfile. 当我们用 ./app paramfile ...

  7. 在开发系统时候运行程序突然报出“WebDev.WebServer40.exe已停止工作”的错误的解决办法

    问题描述:在开发系统时候运行程序突然报出“WebDev.WebServer40.exe已停止工作”的错误,程序调试运行,发现程序在打开数据库时候报错,也就是Connection.Open()处. 但是 ...

  8. 如何查看Linux系统下程序运行时使用的库?

    Linux系统下程序运行会实时的用到相关动态库,某些场景下,比如需要裁剪不必要的动态库时,就需要查看哪些动态库被用到了. 以运行VLC为例. VLC开始运行后,首先查看vlc的PID,比如这次查到的V ...

  9. 第一次安装vs2010无法运行程序,系统找不到exe文件,LINK : fatal error LNK1123: 转换到 COFF 期间失败: 文件无效或损坏

    最近在看数据结构的一些书籍,怎奈代码是c写的,所以安装一个编译器vs2010来测试代码,但是建完文件后编译ok,f5却出现错误:无法启动程序,系统找不到指定文件.上网找了一些解决办法,但是仍然无法解决 ...

随机推荐

  1. android自定义控件一站式入门

    自定义控件 Android系统提供了一系列UI相关的类来帮助我们构造app的界面,以及完成交互的处理. 一般的,所有可以在窗口中被展示的UI对象类型,最终都是继承自View的类,这包括展示最终内容的非 ...

  2. C语言 · 判定数字

    编写函数,判断某个给定字符是否为数字. 样例输入 9 样例输出 yes #include<stdio.h> int main(){ char c; scanf("%c" ...

  3. TODO:小程序开发过程之体验者

    TODO:小程序开发过程之体验者 1. 小程序开发过程,先下载开发者并安装开发者工具,现在腾讯开放测试了,普通用户也可以登录开发者工具,如图普通用户登录为调试类型,但是只能建立无AppID的项目 如果 ...

  4. C#基础篇 - 理解委托和事件

    1.委托 委托类似于C++中的函数指针(一个指向内存位置的指针).委托是C#中类型安全的,可以订阅一个或多个具有相同签名方法的函数指针.简单理解,委托是一种可以把函数当做参数传递的类型.很多情况下,某 ...

  5. iOS开发之再探多线程编程:Grand Central Dispatch详解

    Swift3.0相关代码已在github上更新.之前关于iOS开发多线程的内容发布过一篇博客,其中介绍了NSThread.操作队列以及GCD,介绍的不够深入.今天就以GCD为主题来全面的总结一下GCD ...

  6. 在centos7上安装Jenkins

    在centos7上安装Jenkins 安装 添加yum repos,然后安装 sudo wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins ...

  7. [算法]——归并排序(Merge Sort)

    归并排序(Merge Sort)与快速排序思想类似:将待排序数据分成两部分,继续将两个子部分进行递归的归并排序:然后将已经有序的两个子部分进行合并,最终完成排序.其时间复杂度与快速排序均为O(nlog ...

  8. T-SQL字符串相加之后被截断的那点事

    本文出处:http://www.cnblogs.com/wy123/p/6217772.html 字符串自身相加, 虽然赋值给了varchar(max)类型的变量,在某些特殊情况下仍然会被“截断”,这 ...

  9. 企业shell面试题:获取51CTO博客列表倒序排序考试题

    #!/bin/sh PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin HTMLFILE=/home/oldboy/ht ...

  10. ola.hallengren的SQL Server维护脚本

    ola.hallengren的SQL Server维护脚本 下载地址 http://files.cnblogs.com/files/lyhabc/ola.hallengrenMaintenanceSo ...