L2 开始揭开钢琴的盖子

2023-11-13

L2 开始揭开钢琴的盖子

1. 计算机打开电源时执行的第一条指令

通常是IP指针(或PC指针)指向的内容,由硬件设计者决定。

以 x86 计算机为例:

  1. x86 PC 刚开机时,CPU处于 实模式,寻址方式为 CS:IP
  2. 开机时,CS = 0xFFFF,IP = 0x0000
  3. ROM BIOS 映射区 寻址,地址为 0xFFFF0
  4. 检查 RAM、键盘、显示器、磁盘、……
  5. 将磁盘的 0 磁道 0 扇区(即操作系统的引导扇区)的 512 字节的内容 读入内存 0x7c00
  6. 设置 CS = 0x07c0,IP = 0x0000
地址 内容
0xFFFFFFFF ~ ? ROM BIOS
……
0x100000 ~ 0xF0000 [入口] ROM BIOS 映射区
……
? ~ 0x7c00 留给 0磁道 0 扇区
……
? ~ 0x00000000 ……

2. 0x7c00处存放的代码

磁盘的引导扇区(0 磁道 0 扇区)的 512 字节的内容会被读到内存地址 0x7c00 处。其中包括启动设备的信息,存放着开机后执行的第一段可被控制的程序。
操作系统由此开始

2.1 引导扇区代码:bootsect.s

三个重要字段:

BOOTSEG = 0x7c0
INITSEG = 0x9000
SETUPSEG = 0x9020

bootsect.s:

.global begtext, begdata, begbss, endtext, enddata, endbss
.text	// 文本段
begtext:
.data	// 数据段
begdata:
.bss	// 未初始化数据段
begbss:
entry start	// 关键字 entry 告诉链接器 "程序入口"
start:
	mov ax, #BOOTSEG		mov ds, ax
	mov ax, #INITSEG		mov es, ax
	mov cx, #256
	sub si, si				sub di, di
	rep	movw	// 重复移动 256 个字
	jmpi	go, INITSEG	// 段间跳转

得到两个地址 ds:si = 0x7c00 和 es:di = 0x90000。然后将 0x7c00 处的 256 个字移动到 0x90000 处,腾出内存。


go: mov ax, cs // cs = 0x9000
    mov ds, ax	mov es, ax	mov ss, ax	mov sp, #0xff00
load_setup:	// 载入setup模块
	mov dx, #0x0000		mov cx, #0x0002		mov bx, #0x0200
	mov ax, #0x0200+SETUPLEN	int 0x13	// BIOS 中断
	jnc ok_load_setup
	mov dx, #0x0000
	mov ax, #0x0000 // 复位
	int 0x13
	j 	load_setup // 重读

int 0x13 代表读磁盘扇区的中断;
ah = 0x02 - 读磁盘,al = 扇区数量(SETUPLEN = 4),
ch = 柱面号,cl = 开始扇区,
dh = 磁头号,dl = 驱动器号,
es:bx = 内存地址。
即从第二个扇区开始读 4 个扇区,这 4 个扇区就是 setup 模块所在的扇区,读到内存地址 0x90200 处。


Ok_load_setup: // 载入 setup 模块
	mov dl,#0x00	mov ax,#0x0800 // ah = 8
	int 0x13	movch,#0x00	mov sectors,cx
	mov ah,#0x03	xor bh,bh	int 0x10 // 读光标
	mov cx,#24	mov bx,#0x0007 // 7 是显示属性
	mov bp,#msg1	mov ax,#1301	int 0x10 // 显示字符
	mov ax,#SYSSEG // SYSSEG = 0x1000
	mov es,ax
	call read_it // 读入 system 模块
	jmpi 0,SETUPSEG
……
sectors:	.word 0 // 磁道扇区数
msg1: 	.byte 13,10
		.ascii "Loading system..."
		.byte 13,10,13,10

int 0x10 代表显示 logo,即显示 msg1 中的内容。同时,cx = 24 代表输出的字符数量。
最后 jmpi 0,SETUPSEG,即跳转至 setup 对应的内存地址执行。


read_it:	mov ax,es	cmp ax,#ENDSEG	jb ok1_read
			ret
ok1_read:
	mov ax,sectors
	sub ax,sread // sread 是当前已读扇区数,ax 是未读扇区数
	call read_track // 读磁道

读取 system 模块的相关代码。

3. 小结

打开电源,首先执行 boot(引导扇区的内容),随后 boot 会完成 setup 的读取工作以及 system 的读取工作。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

L2 开始揭开钢琴的盖子 的相关文章

  • 内核驱动程序从用户空间读取正常,但写回始终为 0

    因此 我正在努力完成内核驱动程序编程 目前我正在尝试在应用程序和内核驱动程序之间构建简单的数据传输 我使用简单的字符设备作为这两者之间的链接 并且我已成功将数据传输到驱动程序 但我无法将有意义的数据返回到用户空间 内核驱动程序如下所示 in
  • linux新手关于嵌入式linux设备驱动的问题

    最近在研究linux驱动 正如我读过的那些文章所说 设备驱动程序模块很可能会根据内核的需要自动加载 因此我想知道内核如何确定为特定设备 声卡 I2C spi 设备 等 我也无法彻底想象内核如何在启动时检测每个硬件设备 与嵌入式linux相关
  • 确定 TCP Listen() 队列中当前积压的连接数

    有没有办法找出currentLinux 上 TCP 套接字上等待 Accept 的连接尝试次数 我想我可以在每个事件循环上点击 EWOULDBLOCK 之前计算成功的 Accept 数量 但我使用的是隐藏这些细节的高级库 Python Tw
  • Pthreads - 高内存使用率

    我正在用 C 编写一些东西 在 256Mb 系统上的 Linux 中创建大量 Pthread 我通常有 200Mb 的免费空间 当我使用少量线程运行该程序时 它可以工作 但是一旦我让它创建大约 100 个线程 它就会出现错误 因为系统内存不
  • 选择fasta文件中氨基酸超过300个且“C”出现至少4次的序列

    我有一个包含蛋白质序列的 fasta 文件 我想选择超过 300 个氨基酸且半胱氨酸 C 氨基酸出现超过 4 次的序列 我使用此命令来选择具有超过 300 个 aa 的序列 cat 72hDOWN fasta fasta bioawk c
  • 如何获取与 shell 中的文件名模式匹配的所有文件的总文件大小?

    我正在尝试仅使用 shell 来计算与文件名模式匹配的所有文件 在目录树中 的总大小 以字节为单位 这是我到目前为止所拥有的 find name undo exec stat c s awk 总计 1 END 打印总计 有没有更简单的方法来
  • 在 scapy 中通过物理环回发送数据包

    我最近发现了 Scapy 它看起来很棒 我正在尝试查看 NIC 上物理环回模块 存根上的简单流量 但是 Scapy sniff 没有给出任何结果 我正在做的发送数据包是 payload data 10 snf sniff filter ic
  • 使用 ioctl 在 C++ 中以编程方式添加路由

    我编写了简单的 C 函数 添加了新路线 void addRoute int fd socket PF INET SOCK DGRAM IPPROTO IP struct rtentry route memset route 0 sizeof
  • bash while 循环的布尔表达式中的 -lt 意味着什么?

    我猜测它代表小于基于输出 但是我在哪里可以找到有关此语法的文档 bin bash COUNTER 0 while COUNTER lt 10 do echo The counter is COUNTER let COUNTER COUNTE
  • Ruby:在 Ubuntu 上安装 rmagick

    我正在尝试在 Ubuntu 10 04 上安装 RMagick 看起来here https stackoverflow com questions 1482823 is there an easy way to install rmagic
  • Linux shell 从用户输入中获取设备 ID

    我正在为一个程序编写安装脚本 该程序需要在其配置中使用 lsusb 的设备 ID 因此我正在考虑执行以下操作 usblist lsusb put the list into a array for each line use the arr
  • “git add”返回“致命:外部存储库”错误

    我刚刚进入 git 的奇妙世界 我必须提交我对程序所做的一系列更改 位于名为的目录中 var www myapp 我创建了一个新目录 home mylogin gitclone 从这个目录中 我做了一个git clone针对公共回购 我能够
  • 使用 libusb 输出不正确

    我用libusb编写了一个程序 我怀疑输出是否正确 因为所有条目都显示相同的供应商和产品 ID 以下是代码 include
  • 嵌入清单文件以要求具有 mingw32 的管理员执行级别

    我正在 ubuntu 下使用 i586 mingw32msvc 交叉编译应用程序 我很难理解如何嵌入清单文件以要求 mingw32 具有管理员执行级别 对于我的例子 我使用了这个hello c int main return 0 这个资源文
  • Linux 使用 boost asio 拒绝套接字绑定权限

    我在绑定套接字时遇到问题 并且以用户身份运行程序时权限被拒绝 这行代码会产生错误 acceptor new boost asio ip tcp acceptor io boost asio ip tcp endpoint boost asi
  • 在 docker 中重定向命令输出

    我想为我的服务器做一些简单的日志记录 它是一个在 Docker 容器中运行的小型 Flask 应用程序 这是 Dockerfile Dockerfile FROM dreen flask MAINTAINER dreen WORKDIR s
  • ssh 连接超时

    我无法在 git 中 ssh 到 github bitbucket 或 gitlab 我通常会收到以下错误消息 如何避免它 输出 ssh T email protected cdn cgi l email protection i ssh
  • Tomcat Intellij Idea:远程部署

    RackSpace 云服务器 Ubuntu 12 04 Intellij Idea 11 1 2 Windows 8 Tomcat 7 0 26 JDK 6 在 Intellij Idea 上 当我尝试在远程 Tomcat 7 服务器上运行
  • 在内核代码中查找函数的最佳方法[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我开始浏览内核代码 遇到的一件事是如何跟踪函数调用 结构定义等 有没有一种好的方法可以快速跳转到函数定义并退出 我尝试过 Source N
  • 如何使用 JSch 将多行命令输出存储到变量中

    所以 我有一段很好的代码 我很难理解 它允许我向我的服务器发送命令 并获得一行响应 该代码有效 但我想从服务器返回多行 主要类是 JSch jSch new JSch MyUserInfo ui new MyUserInfo String

随机推荐

  • C++中.cpp和.hpp的区别

    时间 2020 06 02 标签 c cpp hpp 区别 栏目 C C 繁體版 原文 https my oschina net u 4398200 blog 3336507 原文地址 https blog csdn net qzx9059
  • H5中写一个下拉框,点击下拉框内容会出现在文本域中

    朋友出去面试做的面试题 分享了下 我就拿来做做 原题 HTML中有个下拉框 包含 风 雨 雷 电 添加事件 当选择风时 文本域内出现选择
  • 使用proteus仿真集成运放构成的三角波发生电路

    仿真电路图 仿真示波器结果
  • 用python做小游戏——以弹球游戏为例

    本博客使用了Pygame库来创建游戏窗口和处理游戏逻辑 一 代码详细解释 首先 通过调用pygame init 来初始化Pygame库 然后创建一个窗口并设置标题 pygame init screen pygame display set
  • 当全景视频遇到快手

    收到 山巅之处 正午的阳光透过翻滚的云海铺洒在岩石壁上 镶嵌在天边连绵起伏的山峦若隐若现 雄伟壮观 俯瞰去 脚下是天梯般陡峭的山崖 连接着山中绿洲 纵身一跃 映入眼帘的是逐渐清晰的林海 那些拔地而起的树木紧密相连 铸成一座郁郁葱葱的 绿色长
  • docker容器内服务访问宿主机服务

    我的个人博客 逐步前行STEP 本文背景 操作系统 macOs 笔者的docker虚拟机中运行了nginx node服务用来部署一个前后端分离的网站 但是由于docker内的node服务运行效率极低 每次代码更新后也不会自动重新编译 所以准
  • 函数间隔和几何间隔

    问题描述 求一个任意点 到一个超平面的距离 超平面表示 在线性代数中 一个超平面可以用下式表示 y X W T
  • 借助ChatGPT自动生成PPT

    借助ChatGPT自动生成PPT 首先让GPT生成一段markdown格式的PPT内容 尽量描述全面 以什么语言 什么格式 排版等等 打开mindshow网址 点击import and create 选择以markdown方式创建 再次点击
  • c++: 实战详解vector

    目的 本文从实际使用的角度出发 简介C 中vector的基本用法 如增 删 改 查等 并举例说明 增 如下代码演示如何向vector中添加元素 其中 include
  • NotePad++添加到右键快捷方式

    首先看效果图 NotePad 添加到右键快捷方式 接下来是操作方式 首先在桌面上新建一个txt文本文档 然后将写入如下内容 Windows Registry Editor Version 5 00 HKEY CLASSES ROOT she
  • 人才梯队如何搭建,3个维度让你打造一支人才团队

    模型在手 方法我有 文末完整版 一 人才梯队可以不建立吗 二 人才梯队建设的目的 三 梯队人才的培养模型 四 梯队人才的管理 五 人才梯队建设发展通道 人才盘点 素质模型 人才盘点的内容 人才盘点的结果 人才分类 人才选拔 晋升与发展 今日
  • hive中常见的谓词操作符/比较符号

    hive中
  • STM32F103移植FreeRTOS必须搞明白的系列知识---2(FreeRTOS任务优先级)

    STM32F103移植FreeRTOS必须搞明白的系列知识 1 Cortex CM3中断优先级 STM32F103移植FreeRTOS必须搞明白的系列知识 2 FreeRTOS任务优先级 STM32F103移植FreeRTOS必须搞明白的系
  • 一文带你了解芯片制造的6个关键步骤

    在智能手机等众多数码产品的更新迭代中 科技的改变悄然发生 苹果A15仿生芯片等尖端芯片正使得更多革新技术成为可能 这些芯片是如何被制造出来的 其中又有哪些关键步骤呢 智能手机 个人电脑 游戏机这类现代数码产品的强大性能已无需赘言 而这些强大
  • el-radio值无法回显

    首先检查 label 绑定一个动态变量 其次label为number类型可以直接回显 为string类型需要在最外层再加一层单引号
  • 【Android Socket专题】:UDP通信客户端app的demo的实现

    Android Socket 专题 UDP Client客户端 http blog csdn net shankezh article details 50731287 UDP Server服务器 http blog csdn net sh
  • Linux里隐藏的计算器,你知道它的奥秘吗?

    大家都知道 windows下有个计算器工具 我们在工作生活中经常使用到它 但是 你可知Linux下也同样有个计算器吗 当然 良许说的是命令行下的计算器工具 而不是界面型的计算器 良许是Linux应用开发工程师 平时基本是在命令行下工作 所以
  • MYSQL数据类型

    MySQL中定义数据字段的类型对你数据库的优化是非常重要的 MySQL支持多种类型 大致可以分为三类 数值 日期 时间和字符串 字符 类型 数值类型 MySQL支持所有标准SQL数值数据类型 这些类型包括严格数值数据类型 INTEGER S
  • 二. Gateway 网关基础使用示例与自定义全局过滤器

    目录 一 步骤 二 目标服务 三 创建 Gateway 网关服务 三 自定义 GatewayFilter 过滤器 四 通过自定义 GatewayFilter 过滤器实现允许跨域问题 一 步骤 需求 现在有一个服务需要使用 Gateway 网
  • L2 开始揭开钢琴的盖子

    L2 开始揭开钢琴的盖子 1 计算机打开电源时执行的第一条指令 通常是IP指针 或PC指针 指向的内容 由硬件设计者决定 以 x86 计算机为例 x86 PC 刚开机时 CPU处于 实模式 寻址方式为 CS IP 开机时 CS 0xFFFF