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

ARM64内联汇编BL/BLR/BR指令调用异常问题求助

ARM64内联汇编BL调用异常导致main循环无法执行的修复方案

问题根源分析

你的代码核心问题是内联汇编未告知编译器寄存器X30(链接寄存器LR)会被修改,同时存在输出约束与实际汇编逻辑不匹配的问题,导致函数返回地址被破坏,程序执行流异常跳走,因此main函数的for循环无法进入。

具体问题点:

  • BL指令会将当前PC+4写入X30,用于函数返回,但你的内联汇编没有在clobber列表中声明X30,编译器会假设X30的值(即BranchingModes函数的返回地址)保持不变。当myFunction返回后,X30已经被BL修改为myFunction调用后的地址,BranchingModes函数返回时需要的原X30值已丢失,导致程序跳转到错误地址,直接终止或跑飞。
  • 输出约束中声明了[reg0] "=r"(regw0),但汇编代码中从未给regw0对应的寄存器赋值,触发未定义行为,可能进一步破坏寄存器状态。
  • myFunction中的ret x30属于非标准写法,ARM64标准返回指令是ret(默认使用X30的值),冗余写法可能在部分环境下引发问题。

修复步骤

  1. 添加寄存器clobber列表:在内联汇编末尾添加:"x30",告诉编译器X30会被修改,让编译器提前保存、执行后恢复该寄存器的值。
  2. 移除未使用的输出约束:删除[reg0] "=r"(regw0),避免未定义行为。
  3. 修正myFunction的返回指令:将ret x30改为标准的ret指令。
  4. 调整逻辑条件:原if条件要求regw0和regw1都等于10,这永远无法满足,修改为只判断regw1(匹配myFunction的返回值逻辑)。

完整修正代码

#include <stdio.h>

#define LDRARRAYLENGTH   (4)

__asm __volatile
(
    ".global  myFunction               \n\t"
    ".p2align 4                        \n\t"
    ".type    myFunction,%function     \n\t"
    "myFunction:                       \n\t"
           "mov  x0, #10               \n\t"
           "ret                        \n\t"  // 改为标准ARM64返回指令
);

bool BranchingModes(void)
{
    bool BranchingModesFlag = false;

    int regw1 = 0x00;

    __asm __volatile
    (
        "bl myFunction                      \n\t"  // BL调用会修改X30
        "mov  %[reg1],  x0                  \n\t"  // 将返回值存入regw1

        :[reg1] "=r"(regw1)  // 移除未使用的reg0输出约束
        :
        :"x30"  // 声明X30会被修改,让编译器处理寄存器保存
    );

    // 调整条件为只判断regw1,匹配myFunction的返回值逻辑
    if(regw1 == 10)
    {
        BranchingModesFlag = true;
    }
    else
    {
        BranchingModesFlag = false;
    }

    return BranchingModesFlag;
}

int main()
{
    unsigned int i0 = 0x00;
    unsigned int counter = 0x00;

    BranchingModes();

    for(i0=0x00; i0<=10000;  i0++)
    {
        counter = counter  + 1;
    }

    return 0;
}

额外注意事项

  • ARM64内联汇编必须严格遵循调用约定,所有被修改的寄存器(除输出约束指定的)都需要在clobber列表中声明,包括X30、X1-X15等临时寄存器。
  • BL指令用于子程序调用,会自动设置X30为返回地址,子程序返回时直接用ret即可,无需显式指定X30。
  • 输出约束必须与汇编代码中的赋值操作一一对应,避免未定义行为。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 11:25:27