首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Int 10H不在QEMU中工作

Int 10H不在QEMU中工作
EN

Stack Overflow用户
提问于 2016-06-26 17:57:57
回答 1查看 962关注 0票数 3

我正在学习x86实模式编程,并编写了一个使用QEMU进行测试的小型引导加载器。我选择了GNU汇编程序来学习。

以下是程序集代码:

代码语言:javascript
运行
复制
#
# 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

QEMU显示的文本如下:

从硬盘启动..。

The problem:上面的消息是打印出来的,仍然是看起来什么都不做。

我用来组装的脚本链接是:

代码语言:javascript
运行
复制
> 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

链接器脚本是从我在某个地方看到的在线教程中复制的,因为我不知道如何自己创建一个:

代码语言:javascript
运行
复制
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 = .;
}

我是否需要指定任何额外的参数,还是代码中有一些错误?我认为这是堆栈的设置,但尝试了许多可能性,但没有奏效。

如何通过硬盘引导消息并让引导加载程序在屏幕上显示字母m

我的工作平台是Fedora 23。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-06-26 23:45:19

看来,您的链接器脚本是为这样一个环境编写的,在该环境中,将在0x00100000加载受保护模式内核。这对于符合多引导规范的引导加载程序来说是很常见的。像您这样的真正模式引导程序将从磁盘的前512字节读取,并放置在内存中的0x7c00。您将需要一个使用0x7c00起始点的链接器脚本。还可以使用链接器脚本输出引导磁盘签名0xAA 55。

一个基本的引导程序链接器脚本可以类似于这个link.ld

代码语言:javascript
运行
复制
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);
    }
}

您的boot.s没有被告知要生成16位代码。您可以将指令.code16放在程序集文件的顶部,以强制它生成16位指令。您还必须修改GCC命令以编译为16位代码,链接器将需要-melf_i386选项。

引导加载程序代码应该真正设置DS寄存器以及堆栈。因为链接器脚本假定代码位于内存位置0x07c00,所以我们需要将DS设置为零。在分段模型中,物理地址=(segment<<4)+偏移量。DS设置为0,源(基偏移量)为0x7c00将映射到(0<<4)+0x7c00 =物理地址0x07c00,这是BIOS加载引导程序的位置。

我用一些可能有价值的一般引导程序提示写了一个答案。

清理后的boot.s看起来可能如下:

代码语言:javascript
运行
复制
#
# 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

要组装、链接和生成磁盘映像,可以使用:

代码语言:javascript
运行
复制
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

然后,您可以使用映像作为软盘运行它:

代码语言:javascript
运行
复制
qemu-system-i386 -fda HD.img

或作为硬盘映像使用:

代码语言:javascript
运行
复制
qemu-system-i386 -hda HD.img
票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38041478

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档