定义在手动编码的远调用之后出现在调试中的字节

Define byte appearing in debug after a manually encoded far call

我无法让 MASM 接受写成 call 0f000h:1260h 的远调用指令,可能是因为 .

中提出的问题

我决定使用 DB 将其手动编码到我的程序中,而不是乱搞神秘的 MASM 指令:

pushf                      ;IRET will be executed, push flags.
db 9ah,60h,12h,0,0f0h      ;call location f000:1260.
                           ;Location pointed to by int 1c (System timer tick)
                           ;BIOS defaults it to a dummy IRET

在使用 DEBUG.COM 跟踪程序时,我注意到 "DB FE" 在调用指令执行后出现。但是,执行 int 1ch 时不会发生这种情况。这两种跳转到位置f000:1260的方法有什么区别?

我假设 DEBUG 没有将 0xfe(连同以下字节)识别为有效的操作码。我转储位置 f000:1260 以查看那里有哪些字节。

字节 0xfe 和其他一些字节确实存在。 我知道 0xcf 本身就是 IRET 的操作码(这是我期望找到的所有内容),那么这些其他字节是什么?

这是 int 1ch 在位置 0000:0070 的 IVT 条目。

更新

正如 Michael Petch 在他的回答中所说,奇怪的字节构成了 DOSBox 的回调机制。我很想知道如果我尝试在我的主程序中执行此回调会发生什么。

正在执行:

xor ah, ah                 ;select set video mode function
mov al, 13h                ;320x200 256 colors
db 0feh,38h,18h,00h        ;set video mode DOSBox callback.
                           ;Nothing pushed to stack.

好像和执行完全一样:

xor ah, ah                 ;select set video mode function
mov al, 13h                ;320x200 256 colors
int 10h                    ;set video mode.
                           ;Three registers pushed, FLAGS altered (by INT)
                           ;callback occurs, registers popped (by IRET)

唯一的区别是 int 压入 FLAGSCSIP,以及清除 IF 和 TF。该程序返回到 IRET(位于 f000:1264 位置),它会撤消所有这些操作。

"DB FE" 仍然出现在 DEBUG 中。我认为回调仅由 0xfe 和 0x38 的组合触发。它首先尝试执行 0xfe,在这种情况下,它不是有效操作码的一部分并且什么都不做(0xfe 是 inc 操作码的一部分,后跟有效字节),然后在遇到以下 0x38 时发生回调。

0xFE 0x38 不是真正的 Intel x86 处理器上定义的前缀 and/or 指令。在 DOSBox 中,序列 0xFE 0x38 是一个特殊的 4 字节 instruction.The 剩下的两个字节组成一个 16 位值,用作 DOSBox 回调索引号。在这种情况下,索引是 0x0013.

这实际上是调用 DOSBox 本身来执行请求的任务。 DOSBox 将做任何它需要的处理,设置模拟器内部的寄存器,然后 returns。下一条指令是 IRET (0xCF)。这将结束中断并继续处理中断调用之前的指令。

我在查看 DOSBox 代码时发现了这一点。特别是函数 CALLBACK_SetupExtra:

case CB_IRET:
    if (use_cb) {
        phys_writeb(physAddress+0x00,(Bit8u)0xFE);  //GRP 4
        phys_writeb(physAddress+0x01,(Bit8u)0x38);  //Extra Callback instruction
        phys_writew(physAddress+0x02,(Bit16u)callback);     //The immediate word
        physAddress+=4;
    }
    phys_writeb(physAddress+0x00,(Bit8u)0xCF);      //An IRET Instruction

此代码设置 DOSBox 回调,其中回调后需要 IRET