Step to UEFI (302)VC 中的机器码填充

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()函数进行填充,然后在编译完成后使用工具替换这部分机器码为我们自定义的代码。让我们的程序更加灵活,实现更多的功能。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注