图形1: 在你当前的操作系统中用模拟器运行其他操作系统
介绍:
我认为成为专业程序员最重要的一个方法是设计和构建一个自己的操作系统。仅仅了解操作系统的运行原理是远远不够的, 你必须亲自动手去实践。
在学习怎样构建操作时你会学到下面知识:
程序员就像太空中的宇航员,他对乘坐的太空船越了解,知道怎么处理各种问题,他就越有希望安全返回到地球。考虑到程序员,他对计算机和操作系统越了解,他的程序就越可靠,强壮,快速并且更少的Bug。
l 学会可执行文件格式(大有帮助)
l 学会汇编(每个人必须承认,了解汇编是一件非常有意思的事)。
l 了解操作系统背后的运行过程和原理。
l 了解计算机的硬件(CPU 架构, PCI ,SATA,CASH, 网卡, ATA/ATAPI 等等)
l 学会很多新的窍门,这些能在各种编程中给你很大的帮助。
学会这些知识将会给你编程水平带来很大的提高。
如果你仍然没有确信, 试验一下, 你会了知道编操作系统程序是多么有趣。
在这篇文章中我会:
1) 教你怎样用一种简单的方式测试和调试操作系统。
2) 构建和测试你自己的主板。
3) 当用 INT 13h 复位驱动器时, 把驱动器号移到寄存器 DL 中
怎样调试和测试操作系统
Bochs 是一个开源的x86和AMD64 PC 机模拟器,绝大部分是用 C++ 完成,由 GUN 发行。它支持处理器的模拟
(包括保护模式),内存,磁盘,显示器,以太网,BIOS,通常的计算机外围设备.
许多操作系统可以运行在模拟器中,包括 DOS, 各种版本的windows ,BSD 和 Linux。Bochs 可以运行在许多操作系统之上, 包括Windows ,Linnux, Mac OS 和 Xbox。Bochs 经常用于开发操作系统(当模拟的操作系统崩溃时,
实际运行的操作系统却运行正常,这样可以调试模拟的操作系统)。一些人用它在不兼容的操作系统上运行较老的游戏。
按照下面步骤使用 bochs
1. 从 souceforge.net 上下载bochs 。
2. 安装 Bochs
3. 打开安装 Bochs 的目录.
4. 查找 bochsdbg.exe(模拟器+调试器), bochs.exe(模拟器), bximage.exe (磁盘镜像工具)
5. 运行 bximage.exe 创建一张虚拟的 1.44 兆的软盘镜像.
6. 新建文件 "bochsrc.txt"(这个文件是模拟器的初始化文件)写入字符串 "floppya: image="MyOS.img", status=inserted.". (必须是 bximage.exe 创建的或者是任何正确大小的文件)
7. 现在, 需要一些 2 进制数据代替 image(用上篇文章中的代码创建一个 Boot.bin 文件, 替换你刚创建的image 的前 512 字节)
8. 现在运行 bochs.exe, 这会打开 2 个窗口: 控制台窗口(调试)和GUI窗口(显示模拟操作系统的屏幕).
9. 你可以用 bochsdbg.exe 调试你的 image.
10. 你可以创建一个软盘镜像, 硬盘镜像, 光盘镜像, 可以用任何操作系统代替它们并调试它们。
11. 参考 bochs 自带的文档.了解怎样设置断点(lb 0x7c00), 显示内存信息(dump memory x /100bx 0x7c00),
单步(s 1), 读寄存器(r), 继续执行(c), 显示所有寄存器信息 ( dump_cpu ).
典型的主板:
你可以配置并构建整个 PC, 你需要做的就是写PC 的配置文件(bochsrc.txt), 然后把它放在 bochs 安装的文件夹中。这是一个配置文件的例子
#=======================================================================
# ROM-IMAGE:
#=======================================================================
romimage: file=$BXSHARE/BIOS-bochs-latest, address=0xf0000
#=======================================================================
# CPU:
#=======================================================================
cpu: count=1, ips=10000000, reset_on_triple_fault=1
#=======================================================================
# Amount of RAM in MB
#=======================================================================
megs: 32
#=======================================================================
# VGA ROM IMAGE
#=======================================================================
vgaromimage: file= $BXSHARE/VGABIOS-lgpl-latest
#=======================================================================
# VGA:
#=======================================================================
vga: extension= vbe
#=======================================================================
# FLOPPY:
#=======================================================================
floppya: 1_44= "MyImg.img" , status=inserted
#=======================================================================
# ATA0, ATA1, ATA2, ATA3 (Set up Hard disk and CD-ROM IRQ's and I/O address)
#=======================================================================
ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15
ata2: enabled=0, ioaddr1=0x1e8, ioaddr2=0x3e0, irq=11
ata3: enabled=0, ioaddr1=0x168, ioaddr2=0x360, irq=9
#=======================================================================
# ATA[0-3]-MASTER, ATA[0-3]-SLAVE
#=======================================================================
ata0-master: type=disk, path="MyOS/c.img" , mode=flat,
cylinders=20, heads=16, spt=63, translation=none
ata1-master: type=disk, path="MyOS/d.img" , mode=flat,
cylinders=2, heads=16, spt=63, translation=none
ata0-slave: type=cdrom, path=MyOS/cdrom.iso, status=inserted
ata1-slave: type=cdrom, path=MyOS/E.iso, status=inserted
#=======================================================================
# BOOT from:
#=======================================================================
boot: disk
#=======================================================================
# COM1, COM2, COM3, COM4:
#=======================================================================
Com1: enabled=1, dev="COM1"
#=======================================================================
# Parallel ports
#=======================================================================
parport1: enabled=1, file="LPT1"
#=======================================================================
# SB16:
# This defines the SB16 sound emulation.
#=======================================================================
sb16: midimode=1, midi=/dev/midi00, wavemode=1, wave=/dev/dsp,
loglevel=2, log=sb16.log, dmatimer=600000
#=======================================================================
# VGA_UPDATE_INTERVAL:
#=======================================================================
vga_update_interval: 300000
#=======================================================================
# MOUSE: support:
#=======================================================================
mouse: enabled=0
#=======================================================================
# ne2k: NE2000 compatible ethernet adapter
# (Now you can connect to the Internet):
#=======================================================================
ne2k: ioaddr=0x240, irq=9, mac=b0:c4:20:00:00:01,
ethmod=vnet, ethdev="c:/temp"
#=======================================================================
# I440FXSUPPORT: PCI-Controller:
#=======================================================================
i440fxsupport: enabled=1
#=======================================================================
# USB1:
#=======================================================================
usb1: enabled=1
#=======================================================================
# CMOSIMAGE:
#=======================================================================
#cmosimage: file=cmos.img, rtc_init=time0
#-------------------------
# PCI host device mapping (Inserting a PCI device).
#-------------------------
pcidev: vendor=0x1234, device=0x5678
#=======================================================================
# GDBSTUB: (GDB debugger)
#=======================================================================
#gdbstub: enabled=0, port=1234, text_base=0, data_base=0, bss_base=0
#=======================================================================
# IPS: (Instruction Per seconds)
#=======================================================================
ips: 10000000
#=======================================================================
# FOR MORE INFORMATION !!!!!
#=======================================================================
#For more information see the Bches Documentation
#and "bochsrc-sample.txt" (this is in the Bochs directory).
下面是一些非常有用的调试命令:
① c (继续执行指令)
② s [count] ( 执行 count 条指令, 默认是 1 ) 例如 ,s
③ Ctrl+C (停止执行, 返回到命令行)
④ lb addr (设置线性地址指令断点) - 例如, lb 0x7c00
⑤ d n (删除一个断点) -- 例如 : d 1
⑥ x /nuf addr (显示物理内存, nu 数目, f 显示数字格式) - 例如, X /100bx 0x7c00 (以16进制格式显示地址 0x7c00 处的 100 字节内容)
⑦ r 显示 CPU 寄存器和它们的值
⑧ info tab (显示页面地址转换)
⑨ dump_cpu 显示整个 CPU 状态
⑩ set reg = expr (改变 CPU 寄存器为表达式的值) - 例如, set esi = 2*eax+ebx. 更多信息请参考随 bochs 的帮助文档.
名词解释:
ATA : 读写硬盘的协议
ATAPI: 读写光驱的协议
CMOS: 主板上的RAM芯片,由电池供电. 这块RAM 保存了所有的 CMOS 的设置信息.
ROM Image: 只读内存,存有 BIOS 和永久硬件设置.
IPS: CPU 每秒中执行的指令数
VGA: 视频图形适配器
GDB: (调试操作系统的调试器)
PCI 外围组件互连. 这是用于描述怎样把系统的外围组件互连在一起的标准.
你可以得到用 MSVC 6 编译的 Bochs 的源代码. 需要修改一下代码使他可以被 MSVC 6 和 MSVC 2005 编译通过. 改动源代码后会发生什么,例如: 你修改了内部定义 #define 会发生什么。例如 #define BX_DEBUGGER 1 (in Config.h),成功的编译了吗?