VC 的 X86 模式下无法直接使用 _ASM 关键字定义汇编代码,最近偶然看到了VC 支持Intrinsics(内联函数),它是编译器提供的特殊函数,它们直接映射到特定的处理器指令,让你能够在 C++ 代码中使用底层硬件功能。
于是,编写代码测试:
#include <Uefi.h>
#include <Library/UefiLib.h>
#include <Library/ShellCEntryLib.h>
INTN
EFIAPI
ShellAppMain (
IN UINTN Argc,
IN CHAR16 **Argv
)
{
UINT32 cpuInfo[4];
// CPUID 指令
__cpuid(cpuInfo, 1);
//NOP 指令
__nop();
return(0);
}
使用 /FACS 查看生成的汇编代码,对应片段如下:
ShellAppMain PROC ; COMDAT
; 19 : {
$LN3:
00000 48 89 54 24 10 mov QWORD PTR [rsp+16], rdx
00005 48 89 4c 24 08 mov QWORD PTR [rsp+8], rcx
0000a 53 push rbx
0000b 48 83 ec 10 sub rsp, 16
; 20 : UINT32 cpuInfo[4];
; 21 :
; 22 : // CPUID 指令
; 23 : __cpuid(cpuInfo, 1);
0000f b8 01 00 00 00 mov eax, 1
00014 33 c9 xor ecx, ecx
00016 0f a2 cpuid
00018 4c 8d 04 24 lea r8, QWORD PTR cpuInfo$[rsp]
0001c 41 89 00 mov DWORD PTR [r8], eax
0001f 41 89 58 04 mov DWORD PTR [r8+4], ebx
00023 41 89 48 08 mov DWORD PTR [r8+8], ecx
00027 41 89 50 0c mov DWORD PTR [r8+12], edx
; 24 :
; 25 : __nop();
0002b 90 npad 1
; 26 :
; 27 : return(0);
0002c 33 c0 xor eax, eax
; 28 : }
0002e 48 83 c4 10 add rsp, 16
00032 5b pop rbx
00033 c3 ret 0
ShellAppMain ENDP
可以看到编译后生成了对应的汇编代码(也就是机器码)。特别是 _NOP() 函数,直接生成了0x90 这样的机器码。使用这样的思路可以在代码中使用 _NOP()函数进行填充,然后在编译完成后使用工具替换这部分机器码为我们自定义的代码。让我们的程序更加灵活,实现更多的功能。