当前位置: 首页 > article >正文

操作系统启动实验

简单的操作系统
汇编代码
; hello-os
; TAB=4

		ORG		0x7c00			; 指明程序装载地址

; 标准FAT12格式软盘专用的代码 Stand FAT12 format floppy code

		JMP		entry
		DB		0x90
		DB		"HELLOIPL"		; 启动扇区名称(8字节)
		DW		512				; 每个扇区(sector)大小(必须512字节)
		DB		1				; 簇(cluster)大小(必须为1个扇区)
		DW		1				; FAT起始位置(一般为第一个扇区)
		DB		2				; FAT个数(必须为2)
		DW		224				; 根目录大小(一般为224项)
		DW		2880			; 该磁盘大小(必须为2880扇区1440*1024/512)
		DB		0xf0			; 磁盘类型(必须为0xf0)
		DW		9				; FAT的长度(必??9扇区)
		DW		18				; 一个磁道(track)有几个扇区(必须为18)
		DW		2				; 磁头数(必??2)
		DD		0				; 不使用分区,必须是0
		DD		2880			; 重写一次磁盘大小
		DB		0,0,0x29		; 意义不明(固定)
		DD		0xffffffff		; (可能是)卷标号码
		DB		"HELLO-OS   "	; 磁盘的名称(必须为11字?,不足填空格)
		DB		"FAT12   "		; 磁盘格式名称(必??8字?,不足填空格)
		RESB	18				; 先空出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			; 给SI加1
		CMP		AL,0
		JE		fin
		MOV		AH,0x0e			; 显示一个文字
		MOV		BX,15			; 指定字符颜色
		INT		0x10			; 调用显卡BIOS
		JMP		putloop
fin:
		HLT						; 让CPU停止,等待指令
		JMP		fin				; 无限循环

msg:
		DB		0x0a, 0x0a		; 换行两次
		DB		"hello, world"
		DB		0x0a			; 换行
		DB      "hello MYOS,K1T000"
		DB		0x0a			; 换行
		DB		0

		RESB	0x7dfe-$		; 填写0x00直到0x001fe

		DB		0x55, 0xaa

利用工具构建
makefile

  1. Makefile 的功能

Makefile 是一种用于自动化构建过程的脚本文件,通常与 make 工具一起使用。在开发中,它定义了如何编译和链接代码,如何生成目标文件,如何处理依赖关系等。通过 make 命令,开发人员可以根据 Makefile 中的指令自动执行任务,比如编译源代码、创建可执行文件、生成镜像文件等。

具体来说,Makefile 包含:

  • 目标(target):如 helloos.imghelloos.bin 等生成的文件。
  • 规则(rule):定义如何生成目标文件的步骤。
  • 依赖关系(dependency):指定哪些文件或目标是当前目标的依赖。
  • 命令(command):用于生成目标文件的具体操作。
采用汇编
  1. 为什么用汇编语言写操作系统?

写操作系统时,选择使用汇编语言通常有以下几个原因:

(1) 操作系统对硬件的直接控制

操作系统,尤其是引导程序、内核的早期部分,需要直接控制硬件资源(如 CPU、内存、硬盘等)。汇编语言提供了极低级别的控制,使你能够精确地操作硬件,比如设置中断向量、控制内存映射等。

在操作系统启动的早期阶段(引导加载程序),需要与硬件打交道,这时 C 语言的抽象就不再合适,汇编提供的直接访问硬件的能力是必要的。

(2) 性能和效率

汇编语言是一种低级语言,通常比高级语言(如 C 语言)更高效。对于内核的某些关键部分,使用汇编可以实现非常高效的操作,如上下文切换、任务调度等。

(3) 学习和理解底层原理

通过汇编语言写操作系统的早期部分,你可以深入了解计算机的底层架构,包括 CPU 寄存器、栈操作、中断机制等。这对理解操作系统的工作原理非常有帮助。

  1. 为什么不直接用 C 语言写操作系统?

虽然 C 语言在编写操作系统时非常流行,但它并不是完全适合于操作系统所有部分的语言。操作系统的早期阶段(如引导加载程序)确实需要使用汇编语言。以下是一些原因,解释为什么 C 语言通常不会在操作系统的整个开发过程中取代汇编语言:

(1) 操作系统的启动过程

在操作系统启动的初期阶段,CPU 和硬件设备的控制非常直接。你必须配置中断、设置段寄存器、初始化内存等,这些操作 C 语言通常做不到。C 语言对硬件的抽象非常强,它需要操作系统提供的运行时环境来支持,而在操作系统的引导加载过程中(也就是 bootloader 阶段),这些环境尚未建立。

(2) C 语言依赖于运行时库

C 语言虽然非常接近硬件,但它依赖于操作系统的运行时库(例如标准库、系统调用等),这些库在操作系统本身没有完成之前无法使用。操作系统内核的开发必须考虑到这些库在编译时没有定义的情况,因此,直接使用 C 语言的执行环境并不适合操作系统的最初开发。

(3) 操作系统设计中的低级任务

有些操作系统的设计任务需要处理直接与硬件相关的低级任务。例如,操作系统的中断处理、设备驱动、任务调度等,需要非常精确的控制和高效的代码。这些任务用汇编语言编写时更为简单和高效,而在 C 语言中,编译器的优化有时会使代码变得不够高效,特别是与硬件交互时。

(4) 更好的移植性和可维护性

尽管操作系统开发时可能会用汇编语言,但现代操作系统的核心部分通常还是会用 C 语言开发。因为 C 语言具备较好的移植性、可维护性和易读性,尤其是相对于汇编语言。汇编语言的代码是与硬件架构紧密耦合的,因此难以移植,而 C 语言能够在不同的硬件平台上进行相对容易的移植。

关于 Make 的使用

Make 是一个自动化工具,主要用于自动化编译和构建过程。它可以让你通过一个 Makefile 文件定义如何从源代码生成目标文件(如 .o 文件、可执行文件等)。让我们来看一下如何使用 Make 来编译一个汇编语言编写的操作系统。

基本的 Makefile 结构

一个简单的 Makefile 包含以下几个基本部分:

  • 目标(target):你希望生成的文件,比如 .o 文件、最终的可执行文件。
  • 依赖(dependency):生成目标所需要的源文件。
  • 规则(rule):从依赖生成目标的命令。

假设你有一个简单的操作系统源码,包含以下文件:

  • boot.asm:引导程序(使用汇编语言编写)
  • kernel.asm:操作系统内核(使用汇编语言编写)
  • link.ld:链接脚本,用于将生成的目标文件链接成最终的可执行镜像

make 工具不仅仅用于编译操作系统项目,它实际上是一个非常通用的自动化构建工具,广泛应用于各种编程项目中,无论是 C 语言、C++、汇编语言,还是其他语言的项目。它的核心功能是通过 Makefile 自动化地管理源代码的编译、链接等过程,使得项目的构建变得更加高效和可重复。

make 的应用场景

make 工具可以用于编译许多类型的项目,常见的包括:

  • C/C++ 项目:这是 make 最常见的应用场景,尤其是在大型项目中,可以帮助管理多个源文件的编译与链接。
  • Python 项目:虽然 Python 本身不需要编译,但 make 可以用于自动化测试、打包、清理等任务。
  • Java 项目:尽管 Maven 或 Gradle 是更常用的构建工具,但 make 也可以用于编译 Java 源文件。
  • 汇编语言项目:正如你在操作系统开发中看到的,make 也可以用来自动化汇编语言文件的编译过程。
  • 其他脚本语言:对于 Bash 脚本、Ruby 脚本等,make 可以用来执行特定任务,如运行测试、部署应用等。
编译

make file 或者直接 nask.exe helloos.nas helloos.img

2、虚拟机启动操作系统

Step1:启动VMware,创建一个新的虚拟机MyOS(注意加上软盘驱动器);

Step2:设置从软盘镜像文章中启动系统,文件为刚做好的helloos.img

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
Step3:启动该虚拟机
image.png

系统调用

Linux系统中,用户程序可以通过隐式调用或显示调用使用系统调用。

隐式调用——用户通过封装了系统调用的API使用系统调用

显式调用——使用syscall()函数实现调用,int syscall(int number,…),number是系统调用号

基础

syscall 并不仅仅用于获取进程 ID(PID),它是用于直接与操作系统内核交互的一种方式,允许你调用任何支持的系统调用。syscall 函数是一个低级接口,通过它你可以直接发起操作系统的系统调用。

syscall 的基本用法

syscall 函数是一个系统调用接口,允许你通过系统调用号来调用操作系统内核提供的底层功能。它的基本签名通常如下:

c

long syscall(long number, ...);

  • number 是系统调用的编号,也就是操作系统为每个系统调用分配的一个唯一的数字(如 SYS_getpidSYS_read 等)。
  • 后面的 ... 是系统调用的参数,具体取决于你要调用的系统调用。
syscall 支持的系统调用

syscall 函数是通用的,可以用来调用几乎所有的系统调用,不仅仅是 getpid。以下是一些常见的可以通过 syscall 调用的操作系统系统调用:

  1. 进程管理相关的系统调用

    • SYS_getpid:获取当前进程的 PID(进程 ID)。
    • SYS_fork:创建一个新的进程(子进程)。
    • SYS_exit:使当前进程退出。
    • SYS_getppid:获取父进程的 PID。
    • SYS_waitpid:等待子进程的状态改变。
  2. 文件操作相关的系统调用

    • SYS_open:打开文件。
    • SYS_read:从文件描述符中读取数据。
    • SYS_write:向文件描述符写入数据。
    • SYS_close:关闭文件描述符。
    • SYS_lseek:设置文件指针的位置。
  3. 内存管理相关的系统调用

    • SYS_brk:改变数据段的结束地址。
    • SYS_mmap:内存映射文件或设备到进程的虚拟内存。
    • SYS_munmap:解除内存映射。
  4. 信号和中断相关的系统调用

    • SYS_kill:发送信号给进程。
    • SYS_signal:设置信号处理程序。
  5. 网络操作相关的系统调用

    • SYS_socket:创建一个新的网络套接字。
    • SYS_connect:连接到远程主机。
    • SYS_sendto:向指定的地址发送数据。
    • SYS_recvfrom:从指定的地址接收数据。
  6. 时间和日期相关的系统调用

    • SYS_time:获取系统的当前时间。
    • SYS_gettimeofday:获取当前时间戳。

隐式调用实际上是指别人已经为你封装好了底层的功能,你不需要手动调用底层的系统调用(如 syscall),而是通过更高级的接口来实现相同的功能。这种封装不仅让你在编程时更加方便,也提高了代码的可读性和可维护性。

libc

libc(C 语言标准库,lib 是 “library” 的缩写)是一个包含 C 语言标准函数的库。它为开发者提供了许多标准功能,诸如输入输出(I/O)、内存管理、字符串操作、数学函数等。在类Unix 操作系统中,libc 通常是一个包含系统调用封装的共享库。

实验
#include <syscall.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>

int main (viod) {
	long ID1, ID2;
	ID1=syscall(SYS_getpid);     /*显式系统调用*/
	printf(syscall(SYS_getpid)=%ld\n”, ID1);
	ID2=getpid();                /*使用libc封装的隐式系统调用*/
	printf(getpid()=%ld\n”, ID2);
 	return(0);
}

http://www.kler.cn/a/398515.html

相关文章:

  • gitlab和jenkins连接
  • Gin 框架中间件详细介绍
  • 蓝桥杯备赛(持续更新)
  • Flume 单机与集群部署详细教程
  • 【Linux庖丁解牛】—Linux基本指令(下)!
  • Spring Boot 启动时修改上下文
  • 引领企业未来数字基础架构浪潮,中国铁塔探索超大规模分布式算力
  • 机器学习(贝叶斯算法,决策树)
  • Git与GitLab的企业实战 笔记(尚硅谷)
  • 计算机编程中的异步编程模型及其在提升应用响应性中的作用
  • 算法——两两交换链表中的节点(leetcode24)
  • 背包问题总结
  • SQL初步注入
  • 微服务day08
  • H3C NX30Pro刷机教程-2024-11-16
  • 《生成式 AI》课程 第3講 CODE TASK 任务2:角色扮演的机器人
  • 【HarmonyOS】Hdc server port XXXX has been used.Configure environment variable
  • C++创建型模式之原型模式
  • npm、yarn、pnpm 切换查看镜像源笔记
  • OceansGallerie趣味游戏:带领Web2用户无缝融入Web3世界
  • spring基础题笔记(1)
  • (长期更新)《零基础入门 ArcGIS(ArcMap) 》实验一(下)----空间数据的编辑与处理(超超超详细!!!)
  • 如何在 Ubuntu 上安装 RStudio IDE(R语言集成开发环境) ?
  • K8S创建云主机配置docker仓库
  • Spring Boot项目pom.xml文件详解
  • css初始化(二十三课)