上代码先:
; hello-os ; TAB=4 ORG 0x7c00 JMP entry DB 0x90 DB "HELLOIPL" DW 512 DB 1 DW 1 DB 2 DW 224 DW 2880 DB 0xf0 DW 9 DW 18 DW 2 DD 0 DD 2880 DB 0,0,0x29 DD 0xffffffff DB "HELLO-OS " DB "FAT12 " RESB 18 entry: MOV AX,0 MOV SS,AX MOV SP,0x7c00 MOV DS,AX MOV ES,AX MOV SI,msg putloop: MOV AL,[SI] ADD SI,1 CMP AL,0 JE fin MOV AH,0x0e MOV BX,15 INT 0x10 JMP putloop fin: HLT JMP fin msg: DB 0x0a, 0x0a DB "hello, world" DB 0x0a DB 0 RESB 0x7dfe-$ DB 0x55, 0xaa
;这个程序有几个重要的地方需要讲解一下:
知识点一:为什么ORG要设置成0x7c00
这里指定这个很重要,ORG指令来源英文"origin",意思是"源头,起点"。它会告诉汇编器,程序要从指定的
这个地址开始,也就是要把程序装载到内存中的指定位置,那为什么这里就是要指定成地址是0x7c00,那么这里就要讲讲BIOS
BIOS就是基本输入输出系统了,Intel 8086可以访问1MB的内存空间,地址范围为0x00000到0xFFFFF。出于各方面的考虑,计算
机系统的设计者将这1MB的内存空间从物理上分为几个部分086有20根地址线,但并非全都用来访问DRAM,也就是内存条。事实上,
这些地址线经过分配,大部分用于访问DRAM,剩余的部分给了只读存储器ROM和外围的板卡与DRAM不同,只读存储器(Read Only
Memory,ROM)不需要刷新,它的内容是预先写入的,即使掉电也不会消失,但也很难改变。这个特点很有用,比如,可以将一些
程序指令固化在ROM中,使处理器在每次加电时都自动执行。处理器醒来后不能饿着,这是很重要的。
在以Intel 8086为处理器的系统中,ROM占据着整个内存空间顶端的64KB,物理地址范围是0xF0000~0xFFFFF,里面固化了开机时要执行的指令;
DRAM占据着较低端的640KB,地址范围是0x00000~0x9FFFF;中间还有一部分,分给了其他外围设备,这个以后再说。因为8086加电或者复位时,
CS=0xFFFF,IP=0x0000,所以,它取的第一条指令位于物理地址0xFFFF0,正好位于ROM中,那里固化了开机时需要执行的指令。处理器取指令执
行的自然顺序是从内存的低地址往高低地址推进。如果从0xFFFF0开始执行,这个位置离1MB内存的顶端(物理地址0xFFFFF)只有16个字节的长度,
一旦IP寄存器的值超过0x000F,比如IP=0x0011,那么,它与CS一起形成的物理地址将因为溢出而变成0x00001,这将回绕到1MB内存的最低端。
所以,ROM中位于物理地址0xFFFF0的地方,通常是一个跳转指令,它通过改变CS和IP的内容,使处理器从ROM中的较低地址处开始取指令执行。
在NASM汇编语言里,一个典型的跳转指令像这样:
jmp 0xf000:0xe05b
在这里,“jmp”是跳转(jump)的简化形式;0xf000是要跳转到的段地址,用来改变CS寄存器的内容;0xe05b是目标代码段内的偏移地址,
用来改变IP寄存器的内容。一旦执行这条指令,处理器将开始从指定的“段: 偏移”处开始重新取指令执行。
这块ROM芯片中的内容包括很多部分,主要是进行硬件的诊断、检测和初始化。所谓初始化,就是让硬件处于一个正常的、默认的工作状态。最后,
它还负责提供一套软件例程,让人们在不必了解硬件细节的情况下从外围设备(比如键盘)获取输入数据,或者向外围设备(比如显示器)输出数
据。设备当然是很多的,所以这块ROM芯片只针对那些最基本的、对于使用计算机而言最重要的设备,而它所提供的软件例程,也只包含最基本、最
常规的功能。正因为如此,这块芯片又叫基本输入输出系统(Base Input & Output System,BIOS)ROM。在读者缺乏基础知识的情况下讲述ROM-BIOS
的工作只会越讲越糊涂,所以这些知识将会分散在各个章节里予以讲解。
ROM-BIOS的容量是有限的,当它完成自己的使命后,最后所要做的,就是从辅助存储设备读取指令数据,然后转到那里开始执行。基本上,这相当于接力赛中的交接棒。
,ROM-BIOS将读取硬盘主引导扇区的内容,将它加载到内存地址0x0000:0x7c00处(也就是物理地址0x07C00),然后用一个jmp指令跳到那里接着执行:
jmp 0x0000:0x7c00
第二:ROM-BIOS将读取硬盘主引导扇区是哪里?
硬盘的第一个扇区是0面0道1扇区,或者说是0头0柱1扇区,这个扇区称为主引导扇区
第三:这里的DS和ES寄存器为什么设置成0呢?
因为我们上面说过,ROM-BIOS读取硬盘主引导扇区后,会将内容加载到内存地址0x0000:0x7c00位置,那么很明显,这里的段地址是
0x0000,所以把DS,ES都设置成0
第四:这里为什么可以MOV SI,msg呢?这里的msg是一个标号,那么汇编器是怎么进行定位的?
估计有人会说,这还不简单啊,只要知道段地址和偏移量不就可以了吗?通过段地址:偏移量就可以准备的定位到msg的内存地址,但是
我们这里只是知道段地址是0x0000啊,并不知道msg的偏移量是多少啊,那怎么办,汇编器是怎么做到的啊?
下面就引入了一个汇编地址的概念。汇编地址是在程序编译期间,编译器为每条指令确定的汇编位置,也就是每条指令相对于整个
程序开头的偏移量,以字节计,当编译后的程序装入物理内存后,它又是该指令在内存段内的偏移地址。下面看个图你就明白了,从
图可以看出,当编译好的程序加载到物理内存后,它在段内的偏移地址和它在编译阶段的汇编地址相等的。编译后的程序是整体加载
到内存中某个段的,交叉箭头用于指示它们之间的映射关系。之所以箭头交叉,是因为远程序的编译是从上往下的,而内存地址的增长
是从下往上的(低地址往高地址方向增长),那么我们在编译期间就知道了msg的汇编地址,那不就很容易就可以得到其偏移地址吗
第五:看看几个比较重要的寄存器
AX---accumulator:累加寄存器
CX---counter:计数寄存器
DX---data:数据寄存器
BX---base:基址寄存器
SP---stack pointer:栈指针寄存器
BP---base pointer:基址指针寄存器
SI---source index:源变址寄存器
DI---destination index:目的变址寄存器
ES---extra segment:附加段寄存器
CS---code segment:代码段寄存器
SS---stack segment:栈段寄存器
DS---data segment:数据段寄存器
用这几个寄存器来进行编程,本人觉得确实觉得很难,估计是还不怎么熟练这种编程方式。
第六:这个程序中一些重要的指令:
mov 段寄存器,通用寄存器
mov 段寄存器,内存单元
MOV AI, [SI] 这里其实是设略的DS段,全称则是MOV AL, [DS:SI]
add指令需要两个操作数,目的操作数可以是8位或者16位的通用寄存器,或者指向8位或者16位
实际操作数的内存地址;源操作数可以是相同数据宽度的8位或者16位通用寄存器、指向8位或者
16位实际操作数的内存地址,或者立即数,但不允许两个操作数同时为内存单元。相加后,结果
保存在目的操作数中。(重点就是不允许目的操作数和源操作数都是内存单元)
cmp,它需要两个操作数,目的操作数可以是8位或者16位通用寄存器,也可以是8位或者16位内存单
元;源操作数可以是与目的操作数宽度一致的通用寄存器、内存单元或者立即数,但两个操作数同时
为内存单元的情况除外
第六:注意:
虽然我们可以用寄存器来指定内存地址,但可作此用途的寄存器非常有限,只有BX,BP,SI,DI这几个,剩下的
AX,CX,DX,SP不能用来指定内存地址。
MOV AX, [SP]这种写法是错误的
第七:显示文字
首先,既能是要显示文字,就应该看跟显卡有关的函数,这么看来,INT 0X10好像有点关系,这里有个网站可以
查询,不过是日文的 http://community.osdev.info/?(AT)BIOS,当然你也可以上官网去找。
显示一个字符
AH=0X0e;
AL=character code;
BH=0
BL=color code;
返回值:无 是不是看起来很看C的函数调用啊,指定传入函数的参数,就可以达到我们想要的效果了
注:beep,退格(back space),CR,LF都会被当做控制字符处理
所以,如果我们按照这里所写的步骤,往寄存器里代入各种值,再调用INT 0X10,就能顺利地在屏幕上显示一个
字符出来,是不是很简单啊,给变量代值总该会吧,我们要做的事情就是去文档查看要代的值是多少。
第八,HLT指令
HLT是让CPU停止动作的指令,不过并不是彻底停止(如果要彻底停止CPU的动作,只能切断电源),而是让CPU进入待机
状态,只要外部发生变化,比如按下键盘,或是移动鼠标,CPU就会醒过来,继续执行程序。这里的好处就是避免CPU
不停地权力去执行JMP指令,这会使CPU的负荷达到100%,非常的耗电,浪费。
JE指令的只能靠你上网搜索了,判断跳转的指令比较多,需要的时候查一查就OK了。
来张效果图:
后面就开始制作真正的IPL了以及开始导入C语言了,C语言是操作的重头戏了,汇编确实太枯燥了,不过后面的还是会继续大量的介绍汇编的一些用法。
相关推荐
Delphi第一个源码:HelloWorld例子,HelloWorld是个很经典的初学例子,被默认为学习和种语言的第一个小程序,用以在屏幕上输出“HelloWorld”,或是控制台、或是弹出窗口的形式,本程序就是Delphi中的HelloWorld,...
在这个"第一个DWR HelloWorld例子"中,我们将深入理解DWR的基本原理和操作流程,通过实践来学习如何搭建一个简单的DWR应用。 1. **DWR的基本概念** DWR的核心思想是创建一个安全的、高效的、易于使用的AJAX框架。...
【标题】"CXF的第一个例子helloWorld"是一个基础教程,主要介绍了如何使用Apache CXF框架创建一个简单的Web服务。Apache CXF是一个开源的Java框架,它用于构建和开发Web服务,支持SOAP、RESTful等多种通信协议。这个...
【标题】"一个HelloWorld界面程序例子"是一个基础的编程示例,通常用于初次接触编程或新语言教学中。在IT行业中,"Hello, World!"是程序员的第一课,旨在介绍如何在特定编程环境中打印出“Hello, World!”这个简单的...
”是初学者编写的第一个程序,它会在执行时打印出这句话,以此来验证编程环境的正确配置。这个例子可能是表示我们要讨论的是关于编程或者软件开发的基础知识。 标签“hello world”进一步强化了这个主题,可能意味...
"程序是一个经典的起点,用于教授新手如何在特定的编程语言中编写并运行他们的第一个程序。这个简单的程序通常只包含一行代码,用于在控制台上打印出 "Hello, World!" 这个字符串。在这个场景中,我们看到的"Hello...
基础视频。
对于HelloWorld例子,逻辑可能很简单,例如,接收一个包含名字的参数,然后在响应中返回一个问候语,如"Hello, {name}"。 4. **部署服务**:完成服务配置后,将其部署到OSB服务器。部署过程中,OSB会生成必要的运行...
这个简单的程序是许多编程语言教学的第一课,用于向初学者介绍如何在代码中打印出“Hello, World!”这个字符串,以此来验证编译环境的正确配置和基础语法的理解。 在IT领域,“Hello, World!”程序的重要性不言而喻...
"linux 第一个HelloWorld驱动带测试源码.rar" 提供了一个简单的入门级示例,帮助初学者熟悉Linux内核驱动的开发过程。这个压缩包包含了创建、编译和测试一个基本驱动程序的所有必要文件。 首先,"HelloWorld"驱动...
在iOS开发领域,"Hello, World!..."是iOS开发的第一步,通过这个例子,你不仅学会了如何创建基本的UI元素,还了解了Xcode的基本工作流程。继续深入学习,你将能够开发出引人入胜的iPhone应用,服务于全球数百万的用户。
在"Spring第一个HelloWorld"的例子中,我们将学习如何创建一个简单的Spring应用,通过DI来管理对象的生命周期和相互依赖关系。 首先,我们需要创建一个Java类,例如`HelloWorld`,这个类将包含一个方法,如`...
这个“struts2,helloworld例子”是针对初学者的一个典型教程,旨在帮助开发者快速理解和掌握Struts2的基本用法。 首先,我们需要在MyEclipse这样的集成开发环境中搭建Struts2项目环境。这通常包括以下几个步骤: 1...
"例子中,Action类可能只有一个简单的返回字符串"hello"的方法。 然后,我们需要配置struts.xml文件。这个文件定义了Action的映射,包括Action的名称、对应的类以及结果。在"Hello, World!"的例子中,我们可能会有...
通过本教程,你将了解Django的基本结构,并学会创建你的第一个Django项目。 首先,确保你的系统已经安装了Python和Django。如果没有,可以按照以下步骤安装: 1. 安装Python:访问Python官网下载最新版本的Python...
标签“c”表明这个压缩包可能包含了与C语言相关的资源,而“helloworld”则意味着它是关于“Hello, World!”程序的。不过,文件列表中提到的“Sniffer”可能是个意外,因为“Sniffer”通常指的是网络嗅探工具,与...
【标题】:“ibatis 第一个helloWorld” 【知识点详解】: Ibatis,作为一个轻量级的持久层框架,是Java开发中的重要工具,它将SQL语句与Java代码分离,提高了代码的可读性和可维护性。在这个“ibatis 第一个hello...
整个教程分为三个部分:第一部分将深入探讨安装与配置;第二部分将指导如何构建Hello World BPEL流程并进行部署;最后一部分则介绍如何运行已部署的Hello World流程。 #### 二、安装与配置 ##### 2.1 安装与配置 ...
"程序是大多数编程语言教程中的第一个例子,旨在帮助新手快速建立编译、运行程序的基本流程。这个压缩包很可能包含了实现"Hello, World!"程序的源代码文件。 【描述】中提到的链接指向了CSDN(中国软件开发网络)上...
在Android开发领域,"HelloWorld"程序是每个初学者入门时的第一个接触点,它标志着开发者在Android世界中的第一次正式亮相。这个程序虽然简单,但却是理解Android应用开发基础的重要起点。接下来,我们将深入探讨...