超详细汇编注释 操作系统实验二 操作系统的引导(哈工大李治军)(一)

简介: 超详细汇编注释 操作系统实验二 操作系统的引导(哈工大李治军)(一)

实验二 操作系统的引导


Linux 0.11 文件夹中的 boot/bootsect.s、boot/setup.s 和 tools/build.c 是本实验会涉及到的源文件。它们的功能详见《Linux内核0.11完全注释》的 6.2、6.3 节和 16 章。


汇编知识

简要整理了一下这次实验所需的基础汇编知识,可以在下文阅读代码是碰到再回过头来看!


int 0x10


注意,这里ah要先有值,代表内部子程序的编号


功能号 a h = 0 x 03 ,作用是读取光标的位置


输入:bh = 页号

返回:ch = 扫描开始线;cl = 扫描结束线;dh = 行号;dl = 列号

功能号 a h = 0 x 13,作用是显示字符串


输入:al = 放置光标的方式及规定属性,下文 al=1,表示目标字符串仅仅包含字符,属性在BL中包含,光标停在字符串结尾处;es:bp = 字符串起始位置;cx = 显示的字符串字符数;bh = 页号;bl = 字符属性,下文 bl = 07H,表示正常的黑底白字;dh = 行号;dl = 列号

功能号 a h = 0 x 0 e,作用是显示字符


输入:al = 字符


int 0x13

在DOS等实模式操作系统下,调用INT 13h会跳转到计算机的ROM-BIOS代码中进行低级磁盘服务,对程序进行基于物理扇区的磁盘读写操作。


功能号 a h = 0 x 02 ah=0x02ah=0x02,作用是读磁盘扇区到内存


输入:

寄存器

含义
ah 读磁盘扇区到内存
al 需要读出的扇区数量
ch 磁道
cl 扇区
dh 磁头
dl 驱动器
es:bx 数据缓冲区的地址

返回:ah = 出错码(00H表示无错,01H表示非法命令,02H表示地址目标未发现…);CF为进位标志位,如果没有出错 C F = 0


功能号 a h = 0 x 00 ,作用是磁盘系统复位


输入:dl = 驱动器

返回:如果操作成功———— C F = 0 CF=0CF=0,a h = 00 H ah=00Hah=00H

这里我只挑了下文需要的介绍,更多内容可以参考这篇博客BIOS系统服务 —— 直接磁盘服务(int 0x13)


int 0x15

功能号 a h = 0 x 88 ah=0x88ah=0x88,作用是获取系统所含扩展内存大小


输入:ah = 0x88

返回:ax = 从0x100000(1M)处开始的拓展内存大小(KB)。若出错则CF置位,ax = 出错码。

int 0x41

在PC机中BIOS设定的中断向量表中int 0x41的中断向量位置 (4 ∗ 0 x 41 = 0 x 0000 : 0 x 0104 4*0x41 = 0x0000:0x01044∗0x41=0x0000:0x0104)存放的并不是中断程序的地址,而是第一个硬盘的基本参数表。对于100%兼容的BIOS来说,这里存放着硬盘参数表阵列的首地址0xF000:0E401,第二个硬盘的基本参数表入口地址存于int 0x46中断向量位置处.每个硬盘参数表有16个字节大小.

位移

大小 说明
0x00 柱面数
0x02 字节 磁头数
0x0E 字节 每磁道扇区数
0x0F

字节

保留

CF

要了解CF,首先要知道寄存器中有一种特殊的寄存器————标志寄存器,其中存储的信息通常被称为程序状态字。以下简称为flag寄存器。


flag和其他寄存器不一样,其他寄存器是用来存放数据的,都是整个寄存器具有一个含义。而flag寄存器是按位起作用的,也就是说,它的每一位都有专门的含义,记录特定的信息。



flag的1、3、5、12、13、14、15位在8086CPU中没有使用,不具有任何含义。而0、2、4、6、7、8、9、10、11位都具有特殊的含义。


CF就是flag的第0位————进位标志位。在进行无符号数运算的时候,它记录了运算结果的最高有效位向更高位的进位值,或从更高位的借位值。


jnc

在 C F = 0 CF=0CF=0 的时候,进行跳转,即不进位则跳转,下文就是在读入没有出错时,跳转到ok_load_setup


jl

小于则跳转


lds

格式: LDS reg16,mem32


其意义是同时给一个段寄存器和一个16位通用寄存器同时赋值


举例:

地址

100H 101H 102H 103H
内容 00H

41H

02H 03H
LDS AX,[100H]
! 结果:AX=4100H  DS=0302H


可以把上述代码理解为这样一个过程,但实际上不能这么写

mov AX,[100H]
mov DS,[100H+2]


即把低字(2B)置为偏移地址,高字(2B)置为段地址


DF标志和串传送指令

flag的第10位是DF,方向标志位。在串处理指令中,控制每次操作后si、di的增减。


df=0:每次操作后si、di递增

df=1:每次操作后si、di递减

来看一个串传送指令


格式:movsb


功能:相当于执行了如下2步操作


( ( e s ) ∗ 16 + ( d i ) ) = ( ( d s ) ∗ 16 + s i )


如果df=0:(si)=(si)+1,(di)=(di)+1


如果df=1:(si)=(si)-1,(di)=(di)-1


可以看出,movsb的功能是将 d s : s i ds:sids:si 指向的内存单元中的字节送入 e s : d i es:dies:di中,然后根据标志寄存器df位的值,将si和di递增或递减。


也可以传送一个字


格式:movsw


功能:相当于执行了如下2步操作


( ( e s ) ∗ 16 + ( d i ) ) = ( ( d s ) ∗ 16 + s i )


如果df=0:(si)=(si)+2,(di)=(di)+2


如果df=1:(si)=(si)-2,(di)=(di)-2


可以看出,movsw的功能是将 d s : s i ds:sids:si 指向的内存单元中的字节送入 e s : d i es:dies:di中,然后根据标志寄存器df位的值, 将si和di递增2或递减2。


movsb和movsw进行的是串传送操作的一个步骤,一般配合rep使用


格式如下:rep movsb


用汇编语法描述:

s:movsb
 loop s


可见rep的作用是根据cx的值,重复执行串传送指令。由于每执行一次movsb指令si和di都会递增或递减指向后面一个单元或前面一个单元,则 rep movsb就可以循环实现(cx)个字符的传送。


call

(1) 将当前IP或CS和IP压入栈中


(2) 转移


CPU执行“call 标号”时,相当于进行:

push IP
jmp near ptr 标号


ret

ret指令用栈中的数据,修改IP的内容,从而实现近转移


(1) ( I P ) = ( ( s s ) ∗ 16 + ( s p ) )


(2) ( s p ) = ( s p ) + 2


CPU执行ret指令时,相当于进行:

pop IP

改写bootsect.s

打开 bootsect.s



Loading system ...就是开机时显示在屏幕上的字,共16字符,加上3个换行+回车,一共是24字符。我将要修改他为Hello OS world, my name is WCF,30字符,加上3个换行+回车,共36字符。所以图一代码修改为mov cx.#36。


将 .org 508 修改为 .org 510,是因为这里不需要 root_dev: .word ROOT_DEV,为了保证 boot_flag 一定在引导扇区最后两个字节,所以要修改 .org。.org 510 表示下面语句从地址510(0x1FE)开始,用来强制要求boot_flag一定在引导扇区的最后2个字节中(第511和512字节)。


完整的代码如下:

entry _start
_start:
    mov ah,#0x03        ! 设置功能号
    xor bh,bh           ! 将bh置0
    int 0x10            ! 返回行号和列号,供显示串用
    mov cx,#52          !要显示的字符串长度
    mov bx,#0x0007      ! bh=0,bl=07(正常的黑底白字)
    mov bp,#msg1        ! es:bp 要显示的字符串物理地址
    mov ax,#0x07c0      ! 将es段寄存器置为#0x07c0
    mov es,ax           
    mov ax,#0x1301      ! ah=13(设置功能号),al=01(目标字符串仅仅包含字符,属性在BL中包含,光标停在字符串结尾处)
    int 0x10            ! 显示字符串
! 设置一个无限循环(纯粹为了能一直看到字符串显示)
inf_loop:
    jmp inf_loop
! 字符串信息
msg1:
    .byte   13,10           ! 换行+回车
    .ascii  "Welcome to the world without assembly language"
    .byte   13,10,13,10     ! 换行+回车
! 将
.org 510
! 启动盘具有有效引导扇区的标志。仅供BIOS中的程序加载引导扇区时识别使用。它必须位于引导扇区的最后两个字节中
boot_flag:
    .word   0xAA55


Ubuntu 上先从终端进入 ~/oslab/linux-0.11/boot/目录


执行下面两个命令编译和链接 bootsect.s:

$ as86 -0 -a -o bootsect.o bootsect.s
$ ld86 -0 -s -o bootsect bootsect.o


其中 bootsect.o 是中间文件。bootsect 是编译、链接后的目标文件。


需要留意的文件是 bootsect 的文件大小是 544 字节,而引导程序必须要正好占用一个磁盘扇区,即 512 个字节。造成多了 32 个字节的原因是 ld86 产生的是 Minix 可执行文件格式,这样的可执行文件处理文本段、数据段等部分以外,还包括一个 Minix 可执行文件头部,它的结构如下:

struct exec {
    unsigned char a_magic[2];  //执行文件魔数
    unsigned char a_flags;
    unsigned char a_cpu;       //CPU标识号
    unsigned char a_hdrlen;    //头部长度,32字节或48字节
    unsigned char a_unused;
    unsigned short a_version;
    long a_text; long a_data; long a_bss; //代码段长度、数据段长度、堆长度
    long a_entry;    //执行入口地址
    long a_total;    //分配的内存总量
    long a_syms;     //符号表大小
};


6 char(6 字节)+ 1 short(2 字节) + 6 long(24 字节)= 32,正好是 32 个字节,去掉这 32 个字节后就可以放入引导扇区了。


对于上面的 Minix 可执行文件,其 a_magic[0]=0x01,a_magic[1]=0x03,a_flags=0x10(可执行文件),a_cpu=0x04(表示 Intel i8086/8088,如果是 0x17 则表示 Sun 公司的 SPARC),所以 bootsect 文件的头几个字节应该是 01 03 10 04。为了验证一下,Ubuntu 下用命令hexdump -C bootsect可以看到:



去掉这 32 个字节的文件头部

$ dd bs=1 if=bootsect of=Image skip=32

生成的 Image 就是去掉文件头的 bootsect。


去掉这 32 个字节后,将生成的文件拷贝到 linux-0.11 目录下,并一定要命名为“Image”(注意大小写)。然后就“run”吧!

# 当前的工作路径为 /oslab/linux-0.11/boot/
# 将刚刚生成的 Image 复制到 linux-0.11 目录下
$ cp ./Image ../Image
# 执行 oslab 目录中的 run 脚本
$ ../../run


目录
相关文章
|
2月前
|
算法
数据结构实验之操作系统打印机管理器问题
本实验旨在通过实现操作系统中的打印机管理器问题,掌握队列的基本操作如入队、出队等,利用队列的先进先出特性解决先申请先打印的问题。实验包括队列的初始化、入队、出队、打印队列内容等功能,并通过菜单式界面进行交互。实验结果显示基本功能可正常执行,但在连续操作时存在执行失败的情况,需进一步优化。
51 4
|
3月前
|
Linux C语言 iOS开发
MacOS环境-手写操作系统-06-在mac下通过交叉编译:C语言结合汇编
MacOS环境-手写操作系统-06-在mac下通过交叉编译:C语言结合汇编
60 0
|
6月前
|
弹性计算 运维
阿里云操作系统智能助手OS Copilot实验测评报告
**OS Copilot 产品体验与功能反馈摘要** 运维人员发现OS Copilot易上手,文档清晰,助其高效排查故障(8/10分)。愿意推荐并参与开源开发。亮点在于知识问答,能快速筛选答案。相较于竞品,优点是新手友好、文档清晰,但功能扩展性待增强。期望增加系统错误排查与解决方案,并集成ECS等,以优化系统安装流程。
阿里云操作系统智能助手OS Copilot实验测评报告
|
6月前
|
弹性计算 运维 自然语言处理
阿里云操作系统智能助手OS Copilot实验测评报告
OS Copilot是针对Linux的智能助手,助力学习、运维及编程。用户界面直观,自然语言交互方便新手。官方文档详尽,但初次配置略复杂,适合学生和开发者。在提高代码编写和调试效率、系统学习上得分高,功能亮点包括代码生成、问答和命令执行。用户期待更多操作系统支持、自动错误分析和系统排查功能。
193 3
|
6月前
|
弹性计算 人工智能 运维
阿里云操作系统智能助手OS Copilot实验测评报告
阿里云操作系统智能助手OS Copilot实验测评报告
119 2
|
6月前
|
弹性计算 运维
阿里云操作系统智能助手OS Copilot的实验测评报告
OS Copilot 产品体验摘要 用户角色与场景:一位计算机学生使用辅助学习和解决问题,特别是通过代码解释功能加深理解。 易用性与文档:初者可能会觉得有些细节不明确。 帮助程度:用户给予极高评价,对学习帮助大,评分10分,快速定位和解决代码问题,提升学习效率。 推荐与参与:用户愿意推荐给他人。 功能体验:用户尝试了所有功能,对知识问答、辅助编程和命令执行特别感兴趣,尤其是命令执行帮助大。 对比其他产品:OS Copilot优点是便捷、准确。 期望功能:用户希望增加自动报错分析和系统错误排查。 联动体验:用户期待,以实现更全面的工具集。 总结:整体体验积极,用户看好其潜力,期待改进和未来联动。
|
6月前
|
弹性计算 运维 Python
阿里云操作系统智能助手OS Copilot实验测评报告
**OS Copilot 产品测评摘要** - 学生使用,用于学习和编码,发现上手难度较高,指引文档不清晰,特别是Access ID设置和代码复制流程。 - 功能上,评分9分,辅助编程和知识问答功能显著提升了学习效率,减少了错误。 - 愿意推荐,并有兴趣参与开源开发以提升自我。 - 希望增强错误排查,提供具体错误原因和位置。 - 联动ACK智能助手可增强学习效果。 [链接]: https://developer.aliyun.com/topic/instructions-for-os-copilot
|
6月前
|
弹性计算 运维 自然语言处理
阿里云操作系统智能助手OS Copilot的实验测评报告
阿里云OS Copilot是AI驱动的Linux操作系统助手,助于系统管理和运维。学生反馈它在代码解释和编写上有很大帮助,给予8-9分的评价。功能亮点包括自然语言问答、辅助编程和命令解释,简化操作,提升效率。尽管易用,但需基础Linux知识。用户期待更多功能如系统优化建议和代码优化。与ACK智能助手配合,实现故障排查和运维。适合寻求效率提升的个人和团队。
75 0
|
6月前
|
弹性计算 运维 自然语言处理
阿里云操作系统智能助手OS Copilot实验测评报告
阿里云OS Copilot是面向Linux的智能助手,助运维工程师提升效率。易上手,文档清晰,对新人友好。提供自然语言问答、编程辅助,尤善理解与响应。评分10/10,推荐给同行。目前侧重辅助编程,期望支持更多OS、并发命令执行及错误分析。适合集成于ECS等,打造自动化工作流。期待开源版本与社区合作。
103 0
|
6月前
|
弹性计算 运维 安全
操作系统智能助手OS Copilot实验测评报告
**阿里云OS Copilot摘要** OS Copilot是面向开发者和学生的智能助手,尤其对学习编程和运维有显著帮助。虽然初期上手复杂,但其知识问答、辅助编程功能深受好评,评分10分。用户愿推荐给他人,并期待开源参与开发。产品优点包括多功能、便捷性和高准确度,但新手引导需改进。期望增加Windows支持和自动化错误分析功能。通过与ECS等产品联动,OS Copilot能提升整体效率,简化操作,展现云服务的未来潜力。
78 0