操作系统启动实验

embedded/2024/11/19 0:00:11/
简单的操作系统
汇编代码
; hello-os
; TAB=4ORG		0x7c00			; 指明程序装载地址; 标准FAT12格式软盘专用的代码 Stand FAT12 format floppy codeJMP		entryDB		0x90DB		"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				; 不使用分区,必须是0DD		2880			; 重写一次磁盘大小DB		0,0,0x29		; 意义不明(固定)DD		0xffffffff		; (可能是)卷标号码DB		"HELLO-OS   "	; 磁盘的名称(必须为11字?,不足填空格)DB		"FAT12   "		; 磁盘格式名称(必??8字?,不足填空格)RESB	18				; 先空出18字节; 程序主体entry:MOV		AX,0			; 初始化寄存器MOV		SS,AXMOV		SP,0x7c00MOV		DS,AXMOV		ES,AXMOV		SI,msg
putloop:MOV		AL,[SI]ADD		SI,1			; 给SI加1CMP		AL,0JE		finMOV		AH,0x0e			; 显示一个文字MOV		BX,15			; 指定字符颜色INT		0x10			; 调用显卡BIOSJMP		putloop
fin:HLT						; 让CPU停止,等待指令JMP		fin				; 无限循环msg:DB		0x0a, 0x0a		; 换行两次DB		"hello, world"DB		0x0a			; 换行DB      "hello MYOS,K1T000"DB		0x0a			; 换行DB		0RESB	0x7dfe-$		; 填写0x00直到0x001feDB		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.ppmy.cn/embedded/138653.html

相关文章

机器学习基础02

目录 1.特征工程 1.1特征工程概念 1.2特征工程的步骤 1.3特征工程-特征提取 1.3.1字典列表(json)特征提取 1.3.2文本特征提取 英文文本提取 中文文本提取 1.3.3TF-IDF文本特征词的稀有程度特征提取 2.无量纲化 2.1归一化 2.2标准化 2.3fit、fit_transform、transfo…

@ComponentScan:Spring Boot中的自动装配大师

文章目录 1. 什么是ComponentScan注解&#xff1f;2. 为什么需要ComponentScan注解&#xff1f;3. 如何使用ComponentScan注解&#xff1f;4. ComponentScan注解的高级用法5. 注意事项6. 结语推荐阅读文章 在Spring Boot的世界里&#xff0c;自动装配&#xff08;Auto-wiring&a…

git分支合并到远程后如何回滚合并

在GitLab中删除远程仓库的某个特定commit并不是一个直接的操作&#xff0c;因为Git版本控制系统的设计是为了保持历史记录的完整性和不可变性。然而&#xff0c;你可以通过以下步骤来实现删除某个特定的commit&#xff1a; 回退到目标commit之前的状态&#xff1a; 首先&#x…

探秘Spring Boot中的@Conditional注解

文章目录 1. 什么是Conditional注解&#xff1f;2. 为什么需要Conditional注解&#xff1f;3. 如何使用Conditional注解&#xff1f;4. Conditional注解的高级用法5. 注意事项6. 结语推荐阅读文章 在Spring Boot的世界里&#xff0c;配置的灵活性和多样性是至关重要的。有时候&…

【SQL】mysql常用命令

为方便查询&#xff0c;特整理MySQL常用命令。 约定&#xff1a;$后为Shell环境命令&#xff0c;>后为MySQL命令。 1 常用命令 第一步&#xff0c;连接数据库。 $ mysql -u root -p # 进入MySQL bin目录后执行&#xff0c;回车后输入密码连接。# 常用参数&…

前端无感刷新token

摘要&#xff1a; Axios 无感知刷新令牌是一种在前端应用中实现自动刷新访问令牌&#xff08;access token&#xff09;的技术&#xff0c;确保用户在进行 API 请求时不会因为令牌过期而中断操作 目录概览 XMLHttpRequestAxiosFetch APIJQuni.request注意事项&#xff1a; 访问…

【SPIE出版,EI检索稳定】2024年人机交互与虚拟现实国际会议(HCIVR 2024,11月15-17日)

2024年人机交互与虚拟现实国际会议(HCIVR 2024) 2024 International Conference on Human-Computer Interaction and Virtual Reality 官方信息 会议官网:www.hcivr.org 2024 International Conference on Human-Computer Interaction and Virtual Realitywww.hcivr.org 时…

Android Studio | 修改镜像地址为阿里云镜像地址,启动App

在项目文件的目录下的 settings.gradle.kts 中修改配置&#xff0c;配置中包含插件和依赖项 pluginManagement {repositories {maven { urluri ("https://www.jitpack.io")}maven { urluri ("https://maven.aliyun.com/repository/releases")}maven { urlu…