我正在使用 GCC 和一个小的汇编程序引导程序编写一个引导加载程序。我编写了一个puts
例程,使用BIOS中断将字符串打印到显示器上,这些中断似乎没有正确写入字符串。
我的bootstrap汇编程序文件boot.s
包含:
.code16 .section .text
.extern main
.globl start
start:
mov $0x7c0, %ax
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
mov %ax, %gs
jmp main
here:
hlt
jmp here
main.c
中的 C 代码是:
/*
* A 16 bit bootloader.
*/
void putchar_bios(unsigned char ch);
void set_videomode(unsigned short mode);
void puts(char str[]);
#define set_stack(ss, size) \
{ \
__asm__ __volatile__ ( \
"mov %%ax, %%ss\n" \
"mov $512, %%sp\n" : : "a" (ss), "r" (size)\
); \
}
#define set_videomode(mode) \
{ \
__asm__ __volatile__ ( \
"int $0x10\n" : : "a" (mode) \
); \
}
void putchar_bios(unsigned char ch)
{
__asm__ __volatile__ (
"int $0x10\n" : : "a" (0x0E | ch)
);
}
void puts(char *str)
{
while(*str)
putchar_bios(*str++);
}
void main()
{
set_stack(0x07C0, 512);
set_videomode(0x03);
char name[] = "0001234567890";
puts(name);
//This works fine.
// for(i=0; i<15; i++)
// putchar_bios(name[i]);
while(1);
}
我已经在程序集中成功完成了这项工作,但现在我正在尝试将其迁移到 GCC 。我正在使用交叉编译器(i386-gcc)并使用-m16
标志。我使用了自定义链接描述文件。
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);
}
}
我用于在 QEMU 中编译,链接和运行的脚本是:
i386-elf-gcc -m16 -static -ffreestanding -nostdlib -c boot/boot.s
i386-elf-gcc -m16 -static -ffreestanding -nostdlib -c boot/main.c
i386-elf-ld -T link.ld -o b.bin -nostdlib --nmagic boot.o main.o
dd if=b.bin of=HD.img conv=notrunc
#add some noticable garbage to second sector since I also try to read it next
echo "This is the second sector..................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................." | dd seek=512 bs=1 of=HD.img
qemu-system-i386 -hda HD.img # -boot a -s -S
为什么我的程序没有通过puts
函数正确显示字符串?
答案 0 :(得分:1)
我意识到我将段寄存器的值设置为某些垃圾(0x7c0),导致这种情况发生。我修改了我的汇编文件,将段寄存器归零。代码现在看起来像:
.code16
.section .text
.extern main
.globl start
start:
xor %ax, %ax
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
mov %ax, %gs
jmp main
here:
hlt
jmp here
我原本以为编译器会自动初始化段寄存器,但事实并非如此。