调试分析Linux 0.00引导程序
Bochs虚拟机的配置文件
简介 Bochs 虚拟机的配置文件
描述待启动的虚拟机的配置,例如内存大小、启动镜像、网络功能、存储配置。
Bochs运行后,会先查找配置文件,解析模拟器要虚拟的系统相关信息后启动系统。
如何设置从软驱启动
floppya: 1_44="Image", status=inserted
boot: a
如何设置从硬盘启动
ata0-master: type=disk, path="30M.sample", cylinders=615, heads=6, spt=17
boot: disk
如何设置调试选项
log: bochsout.txt:设置日志生成文件。config_interface:配置界面,一系列菜单和对话框。根据平台的不同,有3种配置界面可供选择。display_library:这一行指定了Bochs如何渲染模拟机的显示输出。
# windows
config_interface: win32config
display_library: win32, options="gui_debug"
# Linux
# display_library: x, options="gui_debug"
# MacOS
# display_library: sdl2
win32表示它将使用Windows原生的GUI库。options="gui_debug"表示在GUI中启用调试功能。
Bochs虚拟机的调试技巧
如何单步跟踪?
命令s,或点击Step(s)。
如何设置断点进行调试?
vb / vbreak seg:0ffset在虚拟地址上设置指令断点。lb / lbreak addr在线性地址上设置断点。b / break / pb / pbreak addr在物理地址上设置断点。info break显示当前所有断点的信息。d / del / delete n删除断点 n。(断点是从1开始编号的)
如何查看通用寄存器的值?
registers / reg / r
如何查看系统寄存器的值?
sreg查看段寄存器info flags查看标志寄存器cr查看控制寄存器
如何查看内存指定位置的值?
x /nuf addr检查位于线性地址addr处的内存内容xp /nuf addr检查位于物理地址addr处的内存内容- 参数
n:显示内存单元的计数值,默认为1 - 参数
u:单元大小,默认为wb:bytes 1字节h:halfwords 2字节w:words 4字节g:giantwords 8字节
- 参数
f:显示格式,默认为xx:hex 十六进制数d:decimal 十进制数u:unsigned 无符号十进制o:octal 八进制t:binary 二进制数c:char 对应的字符
如何查看各种表,如 gdt ,idt ,ldt 等?
info gdtinfo gdt [num]显示第num项
info idtinfo ldt
如何查看 TSS?
info tss
如何查看栈中的内容?
print-stack
如何在内存指定地方进行反汇编?
u/disasm/disassemble start endu /10:反汇编从当前地址开始的10条指令
计算机引导程序
如何查看 0x7c00 处被装载了什么?
查看数据: View -> Linear Dump 输入 0x7c00。
反汇编:u/disasm/disassemble 0x7c00 end
如何把真正的内核程序从硬盘或软驱装载到自己想要放的地方;
调用BIOS中断int 0x13功能2从启动盘读取代码。
如何查看实模式的中断程序?
实模式的中断向量表处于内存0开始的地方。中断向量表中中断向量保存着中断程序的入口地址。
如何静态创建 gdt 与 idt ?
在程序中定义数据,静态输入对应的gdt与idt的值。
如何从实模式切换到保护模式?
控制寄存器CR0位0,为标志PE。置位时为保护模式,复位时为实模式。
利用lmsw指令,Load Machine State Word,将PE置为1,切换到保护模式。
调试跟踪 jmpi 0,8 ,解释如何寻址?
此时不是实模式下的段基址与偏移地址的寻址方式了。段值已经是段选择子。
0为偏移量,8为段选择子,对应GDT中的段描述符2。
即从GDT中找到段选择子为 8的段描述符,然后从段描述符中,取出基地址(base address),与偏移量合成线性地址。
该指令执行后,CS:IP即变为0x8:0x0。
实验报告
请简述 head.s 的工作原理
- 初始化GDT和IDT,设置GDHR和IDTR。
- 设置8253定时芯片。
- 设置定时中断门描述符和系统调用陷阱门描述符,分别在IDT表的第8项和第128项。
- 利用
iret命令,跳转到程序 任务0。
记录head.s的内存分布状况

简述head.s 57至62行在做什么
57至62行:
<57> pushl $0x17 # 堆栈段选择符(SS)入栈
<58> pushl $init_stack # 堆栈段偏移(SP)入栈
<59> pushfl # 标志寄存器入栈
<60> pushl $0x0f # 代码段选择符(CS)入栈
<61> pushl $task0 # 代码段偏移(IP)入栈
<62> iret
因为当前head.s 程序是内核程序,特权级别为 0。
由于处于特权级0的代码不能直接把控制权转移到特权级3的代码中执行,但中断返回操作可以。因此,可以利用中断返回指令 iret来启动任务0。
具体操作是,在初始堆栈init_stack中人工设置一个返回环境(初始堆栈也是任务0的用户栈):
- 任务0的 TSS段选择符加载到任务寄存器
LTR。 - 任务0的 LDT段选择符加载到
LDTR。 - 任务0的用户栈指针(
SS:SP),代码指针(CS:IP)以及标志寄存器压入栈中。 - 执行返回中断指令
iret。弹出栈中内容,对应到任务0的堆栈指针、代码指针、标志寄存器。
简述iret执行后,pc如何找到下一条指令?
由于在iret前,栈中压入了代码指针,即代码段的段选择符和偏移量(CS:IP),所以iret后,弹出代码指针,pc根据当前代码指针执行下一条指令。
记录 iret 执行前后,栈是如何变化的?
执行前:可以看到,栈顶自下的5个内容(双字)分别为 IP、CS、EFLAGS、SP、SS。对应压栈的顺序。

执行后:可见,弹出5个双字,

当任务进行系统调用时,即 int 0x80 时,记录栈的变化情况。
任务0进行系统调用int 0x80前:
SS:0x17 ESP:0x0bd8
CS:0x0F EIP:0x10E9
栈空间为任务0的用户栈,即init_stack。

系统调用后:
SS:0x10 ESP:0x0e4c
CS:0x08 EIP:0x166
栈空间为任务0的内核栈。ESP不为0x0e60,可知栈中压入了内容。
观察图,发现栈中压入了5个双字,由栈顶自下分别为 调用前的EIP、调用前的CS、调用前的EFLAGS、调用前的ESP、调用前的SS。
可知,在调用中断时,指令int 0x80,会将当前任务的该 5个寄存器内容压入调用后的栈空间中。也就是被调用者保存。

调试分析Linux 0.00引导程序的更多相关文章
- 通过gdb调试分析Linux内核的启动过程
作者:吴乐 山东师范大学 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.实验流程 1.打开环境 执 ...
- Linux调试分析诊断利器——strace
strace是个功能强大的Linux调试分析诊断工具,可用于跟踪程序执行时进程系统调用(system call)和所接收的信号,尤其是针对源码不可读或源码无法再编译的程序. 在Linux系统中,用户程 ...
- 跟踪分析Linux内核的启动过程小解
跟踪分析Linux内核的启动过程 “20135224陈实 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029 ...
- 20135239 益西拉姆 linux内核分析 跟踪分析Linux内核的启动过程
回顾 1.中断上下文的切换——保存现场&恢复现场 本节主要课程内容 Linux内核源代码简介 1.打开内核源代码页面 arch/目录:支持不同CPU的源代码:其中的X86是重点 init/目录 ...
- 分析Linux内核创建一个新进程的过程【转】
转自:http://www.cnblogs.com/MarkWoo/p/4420588.html 前言说明 本篇为网易云课堂Linux内核分析课程的第六周作业,本次作业我们将具体来分析fork系统调用 ...
- 通过从代码层面分析Linux内核启动来探知操作系统的启动过程
通过从代码层面分析Linux内核启动来探知操作系统的启动过程 前言说明 本篇为网易云课堂Linux内核分析课程的第三周作业,我将围绕Linux 3.18的内核中的start_kernel到init进程 ...
- 跟踪分析Linux内核的启动过程--实验报告 分析 及知识重点
跟踪分析Linux内核的启动过程 攥写人:杨光 学号:20135233 ( *原创作品转载请注明出处*) ( 学习课程:<Linux内核分析>MOOC课程http://mooc.stud ...
- 用 CPI 火焰图分析 Linux 性能问题
https://yq.aliyun.com/articles/465499 用 CPI 火焰图分析 Linux 性能问题 yangoliver 2018-02-11 16:05:53 浏览1076 ...
- 实验 六:分析linux内核创建一个新进程的过程
实验六:分析Linux内核创建一个新进程的过程 作者:王朝宪 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029 ...
- 20135202闫佳歆--week3 跟踪分析Linux内核的启动过程--实验及总结
实验三:跟踪分析Linux内核的启动过程 一.调试步骤如下: 使用gdb跟踪调试内核 qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd r ...
随机推荐
- 文心一言 VS 讯飞星火 VS chatgpt (98)-- 算法导论9.3 4题
四.用go语言,对一个包含n个元素的集合,假设一个算法只使用比较来确定第i小的元素,证明:无需额外的比较操作,它也能找到第 i-1 小的元素和第 n-i大的元素. 文心一言: 在这个问题中,我们要使用 ...
- 快速搭建云原生开发环境(k8s+pv+prometheus+grafana)
欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览 欣宸正在为接下新的Java云原生实战系列原创 ...
- Aveva Marine VBNET 编程系列-搭建开发框架
引用的Dll Aveva.ApplicationFramework.dll Aveva.ApplicationFramework.Presentation 菜单展示效果 创建Attribute,用于反 ...
- 2023-09-30:用go语言,给你一个整数数组 nums 和一个整数 k 。 nums 仅包含 0 和 1, 每一次移动,你可以选择 相邻 两个数字并将它们交换。 请你返回使 nums 中包含 k
2023-09-30:用go语言,给你一个整数数组 nums 和一个整数 k . nums 仅包含 0 和 1, 每一次移动,你可以选择 相邻 两个数字并将它们交换. 请你返回使 nums 中包含 k ...
- Python面向对象——1、什么是异常 2、为何处理异常 3、如何处理异常? 4、何时使用异常处理 网络编程的一些预备知识
文章目录 异常 1.什么是异常 2.为何处理异常 3.如何处理异常? 4.何时使用异常处理 网络编程的一些预备知识 异常 1.什么是异常 异常是程序发生错误的信号.程序一旦出现错误,便会产生一个异常, ...
- it 作形式主语:It's no good doing sth.
It's no good doing sth. 这个 句型其实是一个省 略介词 in 的句型,完整形式是 It's no good in doing sth. 其中, good 是形容词,和介词 in ...
- LVS+keepalived配置高可用架构和负载均衡机制(2)
一.概述 接上文,实际生产场景中,往往存在硬件资源数量的限制,此时需要设置DS节点复用RS节点. 所以往往最常见的架构如下图所示: 3台主机组建真实服务器集群,即3个RS 2个RS兼做DS,构建负载均 ...
- CSS 多行文本超链接下划线动效
先看效果 乍一看,是不是感觉很简单,仔细一瞅发现事情好像没有那么简单. 如果十分钟还没想出怎么实现,那就把简历上的"精通css"改成"了解css"-- 大部分人 ...
- python-手机自动化环境部署
关于ui-automator,google的官方介绍: https://developer.android.google.cn/training/testing/ui-automator https: ...
- 使用LiME收集主机物理内存的内容时发生宕机
作者 pengdonglin137@163.com 现象 在一台ARM64的Centos7虚拟机里加载 https://github.com/504ensicsLabs/LiME 编译出的内核模块时发 ...