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

如何让MASM汇编代码在Linux的.so文件中正常运行

PE格式MASM目标文件迁移Linux后函数指针表重定位失败问题

背景

原有项目使用VC++ + MASM(ml64 14.34.31942)编写.dll,其中C部分作为C#(.NET6)程序的调用包装器,仅提供一个入口点,传递大型状态对象指针并返回int32结果码。现需将该非托管部分迁移至Linux环境,C#程序可正常运行,但非托管库调用出现异常。

迁移尝试方案

  1. C包装器代码:为适配Linux x86-64调用约定,编写C包装器调整寄存器,代码如下(core.c):
#include <stdint.h>

extern int32_t asm_func(void* state);

int wrapper(void *state)
{
  __asm__ volatile(
     "mov %rdi, %rsi \t\n"
     "call asm_func  \t\n");

  return 0;
}

int32_t fnEmulatorCode(void* state) {
  return wrapper(state);
}

注:返回码暂未确定

  1. 编译命令:使用gcc将C代码与ml64生成的PE格式core.obj链接为Linux共享库:
gcc -shared -o EmulatorCore.so -fPIC core.c core.obj -Wall -g -m64
  1. C#引用方式:通过DllImport加载生成的.so文件:
[DllImport(@"./EmulatorCore/EmulatorCore.so")]
private static extern int fnEmulatorCode(ref CpuState state);

故障细节

调用时入口点可正常找到,C包装器的寄存器调整逻辑也能正常工作,但汇编代码中的函数指针表无法在Linux下完成重定位,触发段错误(Windows环境下无此问题)。相关汇编代码片段如下:

lea rax [opcode_00]
lea rax, qword ptr [rax + rbx * 8]  ; rbx is the instruction
jmp qword ptr [rax]                 ; was original jmp qword ptr [rax + rbx * 8]

...

opcode_00   qword   x00_brk         ; $00
opcode_01   qword   x01_ora_indx    ; $01
opcode_02   qword   noinstruction   ; $02
...

其他跳转和符号引用均正常,仅该函数指针表存在问题:

  • 执行nm -gC EmulatorCore.so | grep opcode_00无输出,说明opcode_00等符号未被导出到.so文件中,无法完成重定位(表中指向的函数过程已存在,程序其他部分可运行)。
  • 内存对比显示:Windows下指针表位于库的内存范围内,Linux下表中值均为低偏移量,跳转时读取的地址错误。

待解决问题与需求

  • Linux环境下无法重定位该函数指针表的原因是什么?是gcc优化导致、.NET加载库逻辑错误,还是PE格式目标文件的符号未正确暴露?
  • 无法修改原MASM代码,是否存在工具可将MASM代码转换为NASM等可在Linux下交叉编译的格式?
  • 优先保留原ASM代码,不希望改为标准跳转表(会影响性能且可能引入其他问题)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 16:02:50