QEMU和RAW二进制文件



我正在编译和运行二进制文件(引导部门,第1阶段,第2阶段(进行练习。引导扇区是ASM,第一阶段是ASM运行良好。第二阶段将在0x1000加载,我有一些ASM跳到C代码的开始。我的跳动和电话似乎被两个字节关闭(短(。

我尝试了Bochs和Qemu(逐步浏览(中的代码。所有代码看起来都不错。我什至已经在IDA中分解了它,每个看起来都不错。我认为这可能是我缺乏代码对准知识。

第二阶段从0x1000开始:

0x1000: cli    
0x1001: xor    eax,eax
0x1003: mov    eax,0x1f1a
0x1008: mov    esp,eax
0x100a: sti    
0x100b: jmp    0x1010

第一个跳跃在0x1010(这是拆卸的C代码(:

0x1010: push   0x16b4
0x1015: call   0x14ca   <---
0x101a: add    esp,0x4
0x101d: jmp    0x101d

上面呼叫的0x14ca实际上是在0x000014c9降落,两个字节短。

与上述代码中一样,我希望跳跃或呼叫在操作数地址降落,但它总是缺少两个字节。

这是一个狂野的猜测,实际上可能是错误的。这是基于以下事实:在32位代码中,您编码的相对JMP和呼叫说明为5个字节,在16位代码中,它们为3个字节。5个字节-3个字节= 2个字节。鉴于相对JMP和呼叫目标是基于从下一个指令开始的距离,因此可能会提示可能出了什么问题。

如果我使用此代码:

bits 32
org 0x1000
    cli
    xor    eax,eax
    mov    eax,0x1f1a
    mov    esp,eax
    sti
    jmp    0x1010
    push   0x16b4
    call   0x14ca
    add    esp,0x4
    jmp    0x101d

并与:

组装
nasm -f bin stage2.asm -o stage2.bin

并用:

查看32位解码
ndisasm -b32 -o 0x1000 stage2.bin

我得到:

00001000  FA                cli
00001001  31C0              xor eax,eax
00001003  B81A1F0000        mov eax,0x1f1a
00001008  89C4              mov esp,eax
0000100A  FB                sti
0000100B  E900000000        jmp dword 0x1010
00001010  68B4160000        push dword 0x16b4
00001015  E8B0040000        call dword 0x14ca
0000101A  83C404            add esp,byte +0x4
0000101D  E9FBFFFFFF        jmp dword 0x101d

这看起来正确。但是,如果我用以下方式解码与16位相同的代码。

ndisasm -b16 -o 0x1000 stage2.bin

我得到:

00001000  FA                cli
00001001  31C0              xor ax,ax
00001003  B81A1F            mov ax,0x1f1a
00001006  0000              add [bx+si],al
00001008  89C4              mov sp,ax
0000100A  FB                sti
0000100B  E90000            jmp word 0x100e
0000100E  0000              add [bx+si],al
00001010  68B416            push word 0x16b4
00001013  0000              add [bx+si],al
00001015  E8B004            call word 0x14c8
00001018  0000              add [bx+si],al
0000101A  83C404            add sp,byte +0x4
0000101D  E9FBFF            jmp word 0x101b
00001020  FF                db 0xff
00001021  FF                db 0xff

指令解码不正确,但是JMP和呼叫存在,并转到错误的内存位置。这看起来很像您看到的观察结果。

没有看到您的代码,我希望在您开始在32位受保护模式的0x1000处执行阶段2时。如果您还没有,我怀疑这是您问题的根源。我相信32位编码说明正在以16位实际模式执行。


更新

从评论中,OP建议他们进入32位保护模式,作为输入虚幻模式的过程的一部分。他们相信虚幻模式仍然将指令解码为32位代码,因此是问题。

您通过输入32位保护模式进入虚幻模式,然后返回16位真实模式。虚幻模式仍然是16位真实模式,但隐藏的描述符缓存中的限制设置为0xffffffff(4GIB限制(。一旦返回16位实际模式,您就可以使用32位地址直接在64KIB以上的段中解决内存,但是该代码仍在16位实际模式下运行。

如果您正在为16位虚幻模式编写代码,那么编译器和汇编程序仍需要生成16位代码。如果您打算编写/生成32位代码,那么虚幻模式不是一个选项,您需要输入32位保护模式以执行32位代码。

相关内容

  • 没有找到相关文章

最新更新