Mad*_*n P 1 x86 assembly qemu bios bootloader
我正在学习x86实模式编程,并使用QEMU编写了一个小型引导加载程序来测试它.我选择了GNU汇编程序来学习.
这是汇编代码:
#
# boot.s
#
.section .text
.globl start
start:
//setup stack
mov $0x7c0, %ax
mov %ax, %ss
mov $512, %sp
//setup video
mov $0x0, %eax
mov $0x0, %al
int $0x10
//print a character say 'm'
mov $'m', %al
mov $0x0E, %ah
int $0x10
1:
jmp 1b
Run Code Online (Sandbox Code Playgroud)
QEMU显示屏上显示以下文本:
从硬盘启动...
问题:打印上面的消息,它似乎仍然没有做任何事情.
我用来组装的脚本链接是:
> to assemble : gcc -c boot.s
> to link : ld -T link.ld boot.o -o b.bin
> to put on bootsector of Hard-disk image
dd if=b.bin of=HD.img conv=notrunc
> to attach boot magic
echo -ne "\x55\xaa" | dd seek=510 bs=1 of=HD.img
> to emulate: qemu-system-i386 HD.img
Run Code Online (Sandbox Code Playgroud)
链接器脚本是从我在某处看到的在线教程中复制的,因为我不知道如何自己创建一个:
OUTPUT_FORMAT("binary")
ENTRY(start)
phys = 0x00100000;
SECTIONS
{
.text phys : AT(phys) {
code = .;
*(.text)
*(.rodata)
. = ALIGN(4096);
}
.data : AT(phys + (data - code))
{
data = .;
*(.data)
. = ALIGN(4096);
}
.bss : AT(phys + (bss - code))
{
bss = .;
*(.bss)
. = ALIGN(4096);
}
end = .;
}
Run Code Online (Sandbox Code Playgroud)
我是否需要指定任何额外的参数或代码中有错误?我认为这是堆栈的设置,但尝试了许多可能性,但它没有用.
如何通过硬盘启动消息并让我的引导程序m在屏幕上显示该字母?
我的工作平台是Fedora 23.
您的链接描述文件似乎是针对将在0x00100000加载受保护模式内核的环境编写的.这对于符合多引导规范的引导加载程序很常见.像你这样的实模式引导加载程序将从磁盘的前512个字节读取并放在内存中的0x7c00.您需要一个使用原点0x7c00的链接描述文件.您还可以使用链接描述文件输出引导磁盘签名0xAA55.
基本的引导加载程序链接器脚本可能如下所示link.ld:
OUTPUT_FORMAT("binary");
ENTRY(start);
SECTIONS
{
. = 0x7C00;
.text : AT(0x7C00) {
*(.text);
}
.data : SUBALIGN(0) {
*(.data);
*(.rodata);
}
.bss : SUBALIGN(4) {
__bss_start = .;
*(COMMON);
*(.bss)
. = ALIGN(4);
__bss_end = .;
}
__bss_sizel = SIZEOF(.bss)>>2;
__bss_sizeb = SIZEOF(.bss);
/* Boot signature */
.sig : AT(0x7DFE) {
SHORT(0xaa55);
}
}
Run Code Online (Sandbox Code Playgroud)
您boot.s没有被告知要生成16位代码.您可以将指令.code16放在程序集文件的顶部,以强制它生成16位指令.您还必须修改GCC命令以编译为16位代码,链接器将需要该-melf_i386选项.
您的引导加载程序代码应该真正设置DS寄存器以及堆栈.由于链接器脚本假定代码位于内存位置0x07c00,因此我们需要将DS设置为零.在分段模型中,物理地址=(段<< 4)+偏移.DS设置为0,0x7c00的原点(基址偏移)将映射到(0 << 4)+ 0x7c00 =物理地址0x07c00,这是我们的引导加载程序由BIOS加载的地方.
我用一些可能具有一定价值的一般引导程序提示写了一个答案.
清理后boot.s可能看起来像:
#
# boot.s
#
.code16
.section .text
.globl start
start:
//setup stack
mov $0x7c0, %ax
mov %ax, %ss
mov $512, %sp
xor %ax, %ax # AX = 0
mov %ax, %ds # Set DS = 0 since origin point is 0x7c00
//setup video
xor %ax, %ax # Zero 16-bit AX register (includes AL and AH)
//mov $0x0, %ax # Works but is not preferred for zeroing a reg
int $0x10
//print a character say 'm'
mov $'m', %al
mov $0x0E, %ah
int $0x10
1:
jmp 1b
Run Code Online (Sandbox Code Playgroud)
要组装,链接和生成可以使用的磁盘映像:
gcc -c boot.s -m16
ld -melf_i386 -T link.ld boot.o -o b.bin -nostdlib --nmagic
dd if=b.bin of=HD.img conv=notrunc
Run Code Online (Sandbox Code Playgroud)
然后,您可以使用图像作为软盘运行它:
qemu-system-i386 -fda HD.img
Run Code Online (Sandbox Code Playgroud)
或者作为硬盘驱动器映像使用:
qemu-system-i386 -hda HD.img
Run Code Online (Sandbox Code Playgroud)