自己动手写一个操作系统——loader(1)
前言
上篇文章中,我们写了一个简单的 loader 作为被加载的演示对象。我们知道 loader 是用来加载 kernel 的,今天我们就编写 loader 代码完成这件事情。
实模式下的内存地址
我们计划把 kernel 加载到内存的 0x10000 地址处。
不过面临一个挑战,实模式下地址线为 20 位,寄存器只有 16 位,要想通过寄存器去构成这 20 位的主存地址,必须采取一种特殊的方式。
当指令要想访问某个内存地址时,它通常需要用下面的这种格式来表示:
(段基址:段内偏移)
其中第一个字段是段基址,它的值由段寄存器来提供(一般来说,段寄存器有 6 种,分别为 cs、ds、ss、es、fs、gs),其中 cs 不可以直接通过汇编指令赋值,其它可以。
最终:
物理地址 = (段基址 << 4) + 段内偏移
段基址
我们想要把 kernel 加载到 0x10000 处,就要计算段基址和段内偏移,可知段基址为 0x1000,段内偏移为 0x0。
所以就要给段基址寄存器赋值 0x1000,段偏移寄存器赋值 0x0。
代码
loader.S
.code16
.global _start_start:mov $0x1000, %axmov %ax, %dsmov %ax, %ssmov %ax, %esmov %ax, %fsmov %ax, %gs# 加载 kernel 到内存mov $0x0000, %bx # 要加载到的内存地址mov $0x0003, %cx # ch:磁道号(0x00),cl:起始扇区号(0x03),(扇区 0x01 为 MBR, 扇区 0x02 为 loader)mov $0x02, %ah # ah:读磁盘命令mov $1, %al # al:读取的扇区数量,必须小于128,暂时设置成 1 个扇区mov $0x0080, %dx # dh:磁头号,dl:驱动器号0x80(磁盘1)int $0x13# 跳转到 kerneljmp $0x1000, $0x0000jmp .
我们可以通过 mov 指令,向 ds、ss、es、fs、gs 段寄存器赋值 0x1000,但是 cs 段基址寄存器就不可以使用 mov 指令赋值了,需要使用 jmp 指令。如 jmp $0x1000, $0x0000 就会将 cs 赋值为 0x1000。
start.S
.code16
.global _start_start:jmp .
kernel 的代码目前作为演示就写个简例。
不过注意要在链接时指定代码入口地址为 0x0000(为调试做准备)。
Makefile
OUTPUT=../_build/kernelall:mkdir -p ${OUTPUT}as --32 -g -o ${OUTPUT}/start.o start.Sld -m elf_i386 -Ttext=0x00000 ${OUTPUT}/start.o -o ${OUTPUT}/start.elfobjcopy -O binary ${OUTPUT}/start.elf ${OUTPUT}/kernel.bin objdump -x -d -S ${OUTPUT}/start.elf > ${OUTPUT}/start_dis.txtclean:-rm ${OUTPUT}/*
调试
最终 loader 将 kernel 加载到内存的 0x10000 处,并跳转到该位置运行。
可以看到,段寄存器值全为 0x1000,段内偏移为 0x0(eip),该位置对应的汇编代码为 start.S:5 jmp .
。
自己动手写一个操作系统——loader(1)相关推荐
- 自己动手写一个操作系统——MBR(1)
文章目录 前言 MBR 1) 512 字节镜像 2) 0x55 和 0xAA qemu 运行 参考 前言 上篇<自己动手写一个操作系统--我们能做什么,我们需要做什么>我们介绍到 BIOS ...
- 自己动手写一个操作系统——MBR(2)
前言 上篇文章<自己动手写一个操作系统--MBR(1)>,我们使用 dd 生成了一个 512 字节的镜像,并用 vim 将其最后两个字节修改成了 55 AA,以此来完成了 MBR 的构建. ...
- 自己动手写一个操作系统——MBR(4)_调试_elf_bin
文章目录 前言 elf 文件 指定代码入口地址 添加调试信息 代码 检验 调试 小结 前言 通过 GDB 我们可以跟踪程序的执行, 并且能够看到寄存器的状态, 但是,上面这种调试方式,没有和代码对应起 ...
- 自己动手写一个操作系统——我们能做什么,我们需要做什么
文章目录 计算机启动流程 第一条指令 BIOS MBR loader kernel 总结 计算机启动流程 第一条指令 在开机的一瞬间,也就是上电的一瞬间,CPU 的 CS:IP 寄存器被硬件强制初始化 ...
- 写一个操作系统有多难?自制 os 极简教程
不知道正在阅读本文的你,是否是因为想自己动手写一个操作系统.我觉得可能每个程序员都有个操作系统梦,或许是想亲自动手写出来一个,或许是想彻底吃透操作系统的知识.不论是为了满足程序员们自带的成就感,还是为 ...
- 学习较底层编程:动手写一个C语言编译器
动手编写一个编译器,学习一下较为底层的编程方式,是一种学习计算机到底是如何工作的非常有效方法. 编译器通常被看作是十分复杂的工程.事实上,编写一个产品级的编译器也确实是一个庞大的任务.但是写一个小巧可 ...
- (1)从1开始写一个操作系统
第一章 前言 偶然间使用到了RTX51-tiny做一些东西,它是keil自带的51操作系统,以小巧占用资源少著称,这里不细谈它是如何实现的,反正是一个真正的基于时间片的多任务系统. 往往我们在使用单片 ...
- 自己动手写一个简单的bootloader
自己动手写一个简单的bootloader 15年10月31日19:44:27 (一) start.S 写这一段代码前,先要清楚bootloader开始的时候都做什么了.无非就是硬件的初始化,我们想要写 ...
- [从 0 开始写一个操作系统] 一、准备知识
从 0 开始写一个操作系统 作者:解琛 时间:2020 年 8 月 29 日 从 0 开始写一个操作系统 一.准备知识 1.1 实现方案 1.2 gcc 1.2.1 AT&T 汇编基本语法 1 ...
最新文章
- 分布式事务——消息最终一致性方案
- python的xlwt模块的常用方法
- python 多个列表合并_Python对两个有序列表进行合并和排序的例子
- [html] 写一个布局,当页面滚动一定高时,导航始终固定在顶部,反之恢复原位
- MESSAGE消息发送失败
- 2018尚硅谷大数据视频_韩顺平_Linux视频教程
- 关于冒泡、快排、二分排序算法分析
- HiveQL(三):修改表ALTER TABLE
- .Net Framework4 与.Net Framework4.0 client profile区别问题
- IAR各版本下载链接
- GET 请求能传图片吗?
- 请帮我写一封情书,500字左右
- NPDP产品经理证书在中国有用吗?
- 手机兼职赚钱,分享2个手机可操作的项目给你!
- Asio Streams, Short Reads and Short Writes
- 你要的所有数据源都在这里了!
- C#ObjectArx Cad创建点线块
- Win10+Debian11双系统的配置小记
- 最长回文子串Java
- 微型计算机的外存储器 现在普遍采用什么,当前微型计算机上大部分采用的外存储器,不包含下列哪些?1.硬盘 2.光盘 3.软盘 4.磁带。...
热门文章
- python基于百度智能云实现批量身份证信息识别(附完整代码,可直接使用)
- 40 个让你的网站更加友好的 jQuery 插件
- Windows Thin PC体验 语言包更改(win 7 included)
- 易灵思FPGA-项目设计指南一
- 文本数据增强二(EDA、同义词替换-新增-交换-删除-生成同义句)
- excel2016 卡_Excel情人节卡2016
- 原生1.1.2固件iPhone降级至1.0.2教程
- opera创建房间—比较详细
- Windows 无法访问指定设备、路径或文件。你可能没有适当的权限访问该项目
- QIIME2-单端数据Deblur