02 - Installation and Setup
003 Working with Linux (Ubuntu)
sudo apt-get install gcc
# 9.3.0
gcc -v
sudo apt-get install nasm
# 2.14.02
nasm -v
sudo apt-get install bochs
bximage
为bochs配置
bochs
03 - Boot Up
001 The First Program
BIOS读取引导扇区(0x7c00), 将控制权移交, 第一个扇区的信息也称为主引导记录MBR, 本视频的程序写入磁盘第一个扇区,
当BIOS将其读入内存时, 我们的代码将会执行
在长模式下, 我们无法使用BIOS提供的print服务, 我们使用特定的video mode, 在该模式下可以打印字符
# 在实模式16位下运行
[BITS 16]
# 代码在0x7c00处运行
[ORG 0x7c00]
start:
# 初始化寄存器和堆栈指针
# xor指令 将 ax寄存器清0
xor ax,ax
# 将ax的值(0)复制到ds、es、ss寄存器
mov ds,ax
mov es,ax
mov ss,ax
mov sp,0x7c00
PrintMessage:
# 设置调用打印服务需要的参数
# 13 表示打印字符串
mov ah,0x13
# al 指定了写入模式
# al = 1 表示光标将被放置在字符串的末尾
mov al,1
# bx上半部分bh表示页码, bx下半部分bl存放字符属性的信息
mov bx,0xa
# dx置零, dx上半部分dh代表行, dx下半部分dl代表列
xor dx,dx
# bp 保存要打印的字符串的地址
# 如果要将字符串复制到某个地方(but我们这里只需要知道地址), 使用方括号括起来: [Message]
mov bp,Message
# cx 指定要打印的字符数
mov cx,MessageLen
# 调用指定BIOS服务的中断号, 使用服务
int 0x10
End:
# 使处理器处于停止状态, 此时, 将执行中断
hlt
# 如果一个中断被触发, 处理器将运行hlt之后的指令
# 即这里的jmp End, 而我们跳到End, 继续执行hlt->int 0x10->jmp End, 形成循环
jmp End
Message: db "hello"
# $ 表示当前的汇编位置, 也就是本例中信息的末端
# equ 定义常量的消息长度, 表示字符数
MessageLen: equ $-Message
# 定义db的重复次数
# $$ 表示当前部分的开始
# 这个表达式的结果是: 重复db, 从信息的末尾到偏移量1be的空间都被0填满
# 在1be中, 我们有4个分区条目, 每个大小16字节
times (0x1be-($-$$)) db 0
# 定义第一个条目 -> 希望用U盘启动, 就需要构建看似有效的条目
db 80h # 启动指示器, 80意味着可以启动
# 第一个字节表示磁头值, 第二个字节0-5位用作扇区值, 6-7位用作气缸cylinder值
db 0,2,0 # c,h,s值, c-圆柱体 h-头部 s-扇区
db 0f0h # 分区类型
db 0ffh,0ffh,0ffh # ff是在一个字节中设置的最大值
dd 1 # 起始扇区的LBA(逻辑块地址)地址, 启动过程中使用LBA来加载我们的文件
dd (20*16*63-1) # 分区有多少个扇区 10MB
# 其他条目设置为0
times (16*3) db 0
# 签名 -> 扇区大小假定为512byte
db 0x55
db 0xaa
打印是通过BIOS服务完成, BIOS服务由BIOS中断来访问
# build.sh
# 组装启动文件
# -f bin 表示生成2进制文件
nasm -f bin -o boot.bin boot.asm
# 写入磁盘镜像
# conv=notrunc 不截断文件
dd if=boot.bin of=boot.img bs=512 count=1 conv=notrunc
# asm文件的注释去掉, 再build
chmod +x ./build.sh
sudo ./build.sh
重新安装 bochs