【问题标题】:Cannot find OutputString Offset in UEFI Assembler Application在 UEFI 汇编器应用程序中找不到 OutputString 偏移量
【发布时间】:2021-04-09 10:58:29
【问题描述】:

我想在 Flat Assembler 制作的 EFI 应用程序中通过 UEFI 输出字符串。 这是我的代码

format pe64 dll efi
entry efimain

section '.text' code readable executable

efimain:

        sub rsp, 20h
        mov [EfiHandle], rcx
        mov [SystemTable], rdx
        mov [ReturnAddr], rsp

        lea rdx, [_hello]
        mov rcx, [SystemTable]
        mov rcx, [rcx + 60]
        mov rcx, [rcx + 8]
        call rcx

        jmp $


section '.data' data readable writeable
EfiHandle dq 0
SystemTable dq 0
ReturnAddr dq 0
ConOutAddr dq 0
_hello du 'Hello from UEFI'

基于最新的 UEFI 规范,SystemTable 在 x64 架构上的 RDX 中移交。除了基于规范之外,系统表还描述为

typedef struct { 
EFI_TABLE_HEADER                  Hdr; 
CHAR16                            *FirmwareVendor;
UINT32                            FirmwareRevision;
EFI_HANDLE                        ConsoleInHandle;
EFI_SIMPLE_TEXT_INPUT_PROTOCOL    *ConIn;
EFI_HANDLE                        ConsoleOutHandle;
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL   *ConOut;
EFI_HANDLE                        StandardErrorHandle;
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL   *StdErr;
EFI_RUNTIME_SERVICES              *RuntimeServices;
EFI_BOOT_SERVICES                 *BootServices;
UINTN                             NumberOfTableEntries;
EFI_CONFIGURATION_TABLE           *ConfigurationTable;
} EFI_SYSTEM_TABLE;

表头定义为

typedef struct {
UINT64      Signature;
UINT32      Revision;
UINT32      HeaderSize;
UINT32      CRC32;
UINT32      Reserved;
} EFI_TABLE_HEADER;

EFI_HANDLE 被定义为 VOID *,假设它们表示 x64 架构上的 8 字节指针。

我知道创建结构会更简单,但我想直接进行数学运算以找到正确的偏移量。根据我获得 ConOut 指针的计算,我从 SystemTable Offset + 60(标题 + SystemTable 的其他部分)开始。那么OutPutString方法在输出协议中,定义为:

typedef struct _EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL {
EFI_TEXT_RESET           Reset;
EFI_TEXT_STRING         OutputString;
EFI_TEXT_TEST_STRING     TestString;
EFI_TEXT_QUERY_MODE          QueryMode;
EFI_TEXT_SET_MODE            SetMode;
EFI_TEXT_SET_ATTRIBUTE       SetAttribute;
EFI_TEXT_CLEAR_SCREEN        ClearScreen;
EFI_TEXT_SET_CURSOR_POSITION SetCursorPosition;
EFI_TEXT_ENABLE_CURSOR       EnableCursor;
SIMPLE_TEXT_OUTPUT_MODE      *Mode;
} EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL;

所以在通过mov rcx, [rcx + 60]移动输出协议的偏移量后,我需要跳转到我想调用的OutputString,所以我需要再次跳过8个字节mov rcx, [rcx + 8]

由于我对 Assembler 不太熟悉,我很确定问题一定在于找到 OutputString 方法的正确 OffSet,但我无法发现它。

【问题讨论】:

  • 偏移似乎没问题。但是OutputString 不是一个方法吗?即,看看它的签名,它不需要一个EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL 指针作为它的第一个参数吗?如果在最后两行使用mov rax, [rcx+8] / call rax 会发生什么?

标签: assembly offset uefi fasm


【解决方案1】:

玛格丽特向我指出了解决方案:

  1. 是的,我错过了参数传递部分,第一个参数是指向输出协议的指针(所以它必须在 RCX 中),第二个值是 RDX 中的字符串。所以在 rax 中将指针移动到 OutputString 确实有效

  2. 偏移量仍然不正确。我刚刚又读了一遍规范,上面写着

除非另有说明,否则所有数据类型都是自然对齐的。 结构在等于最大内部的边界上对齐 结构和内部数据的数据被隐式填充到 实现自然对齐。

这样,作为 UINT32 的 FirmwareRevision 的大小实际上也是内存中的 8 个字节(填充)。因此,ConOut 的偏移量将是 0x40(或 64 字节)。

通过这些更改,我终于将我的字符串打印到屏幕上。

【讨论】:

  • 干得好,感谢自我回答。这确实是一个有用的 QA :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-08-08
  • 2019-04-04
  • 1970-01-01
  • 2012-11-05
  • 1970-01-01
  • 2023-03-19
  • 2015-06-27
相关资源
最近更新 更多