You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

读取RIP的MSVC汇编代码移植到GCC的正确实现咨询

你的实现存在以下错误

  • 致命错误:内联汇编中添加了ret指令,执行到这条指令时会直接终止当前父函数(也就是调用_get_addr的GetImageAddress)的执行,不会走后续的代码逻辑,运行直接出错。
  • 符号重定义风险:你使用的_lb是全局符号,如果多个编译单元引入该函数,会出现符号冲突报错。
  • 寄存器使用未声明:你直接修改了rax寄存器,但没有在GCC内联汇编的破坏列表中声明,可能会覆盖编译器在寄存器中存储的其他变量值,导致未定义行为。

关于内联修饰的合理性

你原本的理解有一点偏差:原MSVC实现的_get_addr返回的不是调用者的地址,而是自身函数内部_lb标签的地址,本质是获取当前模块内的一个有效代码段地址,用来向下检索镜像基址。
这种场景下always_inline修饰是合理的:

  • 内联后汇编代码会嵌入到调用者位置,返回的地址是调用者函数内部的地址,依然属于当前模块的代码段,完全满足后续检索基址的逻辑。
  • 还避免了额外的函数调用开销,对EDK2这种底层场景更友好。

正确的GCC移植实现

static __inline__ __attribute__((always_inline)) PVOID _get_addr(void) {
    PVOID pointer;
    __asm__ volatile (
        "call 1f\n"
        "1: pop %[ptr]\n"
        : [ptr] "=r"(pointer)
    );
    return pointer;
}

如果明确要对齐原MSVC实现使用rax寄存器存储返回值,可以写成:

static __inline__ __attribute__((always_inline)) PVOID _get_addr(void) {
    PVOID pointer;
    __asm__ volatile (
        "call 1f\n"
        "1: pop %%rax\n"
        : "=a"(pointer)
    );
    return pointer;
}

注意添加volatile修饰避免GCC优化掉这段汇编代码

功能验证说明

该实现和原MSVC版本功能完全等价:call指令会将下一条指令(也就是局部标签1的位置)的地址压入栈,pop指令将该地址赋值给输出变量,返回的值是当前代码段的一个有效地址,完全满足后续检索当前EFI镜像基址的需求。

内容的提问来源于stack exchange,提问作者l00k

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 14:06:04