内容目录
2024/07/17 更新
目的:
编写一个主引导程序(汇编语言)
可独立运行x86架构的主机(无操作系统)
运行后屏幕上打印字符串;
思路:
引导程序 (类比C语言)
入口: | 0x7c00 | (main)
主题: | 汇编语言 | (C/C++)
底层: | bios中断 | (OS系统调用)
1、关键寄存器设置为 => mov ax,0
2、定义要打印的数据 => db "hello DTOS!"
3、打印预定义好的字符数据 => int 0x10
代码:
boot.asm
org 0x7c00
start:
mov ax, cs
mov ss, ax ;初始化堆栈段,使其与代码段相同。
mov ds, ax ;初始化数据段,使其与代码段相同。
mov es, ax ;初始化附加段,使其与代码段相同。
mov si, msg ;si 通常用于字符串操作或指向数据的地址
print:
mov al, [si]
add si, 1
cmp al, 0x00
je last
mov ah, 0x0e ;设置中断调用的功能号,这里0x0e代表的是在文本模式下输出字符的功能,表示 BIOS 的 teletype 输出功能
mov bx, 0x0f ;表示字符颜色(白色)
int 0x10
jmp print
last:
hlt
jmp last
msg: ;定义输出数据
db 0x0a, 0x0a ; db => define byte, db的定义了两个数据,0a换行符
db "Hello, DTOS!"
db 0x0a, 0x0a
times 510-($-$$) db 0x00 ;不满512字节,补0 $:这里这一行的地址; $$:代表这一段汇编的起始地址; db 0x00判断是否到达数据的末尾
db 0x55, 0xaa ;主引导区MBR,最后占用两个字节,所以上一句用510来减
问题:
1、都初始化为0,那么为什么初始化的时候先是用语句 mov ax, cs ,然后其他的都调用ax?
在早期的 x86 实模式编程中,程序通常将代码段、数据段和堆栈段设置为相同的段,以简化内存管理。通过将 CS 的值加载到 AX,然后将 AX 的值加载到 SS、DS 和 ES,可以确保所有段寄存器都指向相同的段.
直接修改段寄存器(如 mov ss, cs)是不允许的。必须通过通用寄存器(如 AX)来间接修改段寄存器。
结果展示: