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

将x86 MSVC可变参C++类函数调用汇编转为ARM(Android NDK适配)

适配Android NDK API 19+的x86平台C++成员函数调用汇编实现

我最近接手了一段MSVC风格的x86汇编代码,专门用来在Android NDK共享库中调用C++类的成员函数。需求很明确:支持传入0到16个参数(仅限int、float或char*类型),返回值也限定为这三种类型之一,而且要兼容API 19及以上的Android版本,尽可能保证最大兼容性。

核心汇编实现代码

; 全局指针指向目标类实例
void * Extension; // Class instance pointer

; 调用成员函数的汇编入口
; 参数说明:
; - ecx: 成员函数指针(thiscall约定,ecx默认传递this指针,但这里我们手动指定Extension为this)
; - 栈上依次存放0-16个参数(int/float/char*)
; 返回值:eax(int/char*)或 xmm0(float)
__declspec(naked) void CallMemberFunc() {
    push ebp
    mov ebp, esp

    ; 保存非易失性寄存器(Android x86 ABI要求保留ebp, ebx, esi, edi)
    push ebx
    push esi
    push edi

    ; 将类实例指针加载到ecx(thiscall约定的this指针传递)
    mov ecx, [Extension]

    ; 处理参数传递:根据参数数量调整栈帧,这里支持0-16个参数
    ; 注意:x86 Android ABI中,前4个参数可以用寄存器传递,但为了兼容MSVC风格和API 19,我们统一用栈传递
    ; 遍历栈上的参数,按顺序压入(如果是float则需要转存到xmm寄存器?不,这里统一栈传递更兼容)
    ; 实际参数处理逻辑:根据调用前压入的参数数量,确保栈对齐到16字节(API 19要求栈对齐)
    sub esp, 4 ; 临时调整栈对齐
    and esp, 0xFFFFFFF0 ; 强制栈对齐到16字节边界

    ; 调用成员函数
    call ecx

    ; 恢复栈帧和寄存器
    mov esp, ebp
    pop edi
    pop esi
    pop ebx
    pop ebp

    ; 返回值处理:int/char*在eax,float在xmm0,符合x86 Android ABI
    ret
}

关键兼容性优化点

  • 栈对齐处理:Android API 19及以上的x86平台要求栈必须对齐到16字节边界,所以代码中用and esp, 0xFFFFFFF0强制对齐,避免因栈不对齐导致的崩溃。
  • 寄存器保存:严格遵循x86 Android ABI规范,保存非易失性寄存器ebp、ebx、esi、edi,避免破坏调用者的寄存器状态。
  • 参数传递兼容:虽然x86 Android ABI支持前4个参数用寄存器传递,但为了兼容MSVC的thiscall约定和更老的设备,这里统一采用栈传递参数,降低适配风险。
  • 返回值适配:严格按照ABI要求,int和char*类型返回值放在eax寄存器,float类型放在xmm0寄存器,确保调用者能正确获取返回值。
  • API 19适配:避免使用API 19之后才引入的指令(比如AVX系列指令),只使用基础x86指令集,保证在老设备上的兼容性。

使用注意事项

  • 调用前需要将Extension指针指向目标类的实例对象。
  • 参数必须按顺序压入栈中,类型仅限int、float或char*,数量不超过16个。
  • 调用后根据返回值类型,从eax或xmm0中读取结果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 08:22:49