我的预编译 x86 代码可能运行在 16 位(实模式或 16 位保护模式)或 32 位(i386 保护模式)下。如何在运行时从代码中检测它?
我能找到这个 NASM 源代码:
bits 16
cpu 386
pushf
test ax, strict word 0 ; In 32-bit mode this is `test eax, ...', +2 bytes.
jmp short found_16
; Fall through to found_32.
found_32:
bits 32
popf
int 32 ; Or whatever code.
found_16:
bits 16
popf
int 16 ; Or whatever code.
但是我不喜欢它,因为它使用了堆栈。有没有一种解决方案,既不修改任何通用寄存器、段寄存器或标志,也不使用堆栈,而且可以在 8086(仅 16 位模式)和 386(两种模式)上运行?
我已尝试lea esi, [dword esi+0]
过 32 位模式,但在 16 位模式下则转换为非 nop。
请注意,我知道对于大多数程序来说,模式是在编译时决定的(作为架构和平台的一部分),并且它们不必能够在运行时检测模式。对于正常启动的程序,操作系统也会根据文件头选择正确的模式,因此几乎没有意外以错误模式运行完整程序文件的危险。但是,某些程序片段(例如漏洞利用 shellcode)可以从各种运行时检测中受益(包括架构和操作系统)。我还想到了一些其他不太明显的用例。