繁体   English   中英

Qemu和原始二进制文件

[英]Qemu and Raw Binary File

我正在编译并运行二进制文件(引导扇区,第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和CALL指令是5个字节,在16位代码中它们是3个字节。 5个字节 - 3个字节= 2个字节。 鉴于相对JMP和CALL目标是基于距下一条指令开始的距离,它可能会提示可能出错的地方。

如果我拿这个代码:

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和CALL存在并进入错误的存储位置。 这看起来非常像您所看到的观察结果。

在没有看到您的代码的情况下,我希望当您开始在0x1000处执行第2阶段时,您已进入32位保护模式。 如果你还没有,那么我怀疑这是你问题的根源。 我相信32位编码指令正在16位实模式下执行。


更新

根据评论,OP建议他们进入32位保护模式,作为进入虚幻模式的过程的一部分。 他们相信虚幻模式仍会将指令解码为32位代码,从而解决问题。

进入32位保护模式并返回16位实模式,即可进入虚幻模式。 虚幻模式仍然是16位实模式,但隐藏描述符缓存中的限制设置为0xffffffff(4GiB限制)。 一旦返回到16位实模式,您将能够使用32位寻址直接寻址超过64KiB的段中的存储器,但代码仍然以16位实模式运行。

如果您正在为16位虚幻模式编写代码,则编译器和汇编器仍需要生成16位代码。 如果您打算编写/生成32位代码,则不能选择虚幻模式,您需要输入32位保护模式才能执行32位代码。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM