ARM汇编实现的fpow函数调用异常:返回输入参数x问题
分析与修复ARM汇编实现的
fpow函数返回值异常问题 咱们来拆解下你遇到的这个问题——调用fpow(x,y)后返回值总是x,说明你的汇编实现大概率没走通完整的幂运算逻辑,直接把输入的x(也就是初始存在r0里的值)返回了。结合你给出的代码片段,我帮你梳理几个关键问题点和修复方向:
1. 浮点数比较的逻辑错误
你代码里调用__aeabi_fcmpeq前的操作有明显问题:
mov r1, #0 bl __aeabi_fcmpeq
__aeabi_fcmpeq是ARM软浮点环境下的浮点数相等比较函数,调用约定是用r0和r1存放两个待比较的float值。但你此时r0里还是初始的x(只做了mov r4, r0保存,没修改r0),实际在比较的是x == 0,而不是幂运算中需要判断的y == 0!
正确的做法是先把y的值(存在r5里)放到r0,再去和0比较:
mov r0, r5 @ 把y传入r0作为第一个比较参数 mov r1, #0 @ 第二个参数是float 0.0(整数0和float0二进制一致) bl __aeabi_fcmpeq
2. 缺失核心幂运算逻辑
你给出的代码中__aeabi_fcmpeq之后的...是关键缺口。幂运算的核心公式是 x^y = 2^(y * log2(x)),这需要三步核心操作:
- 计算
log2(x):调用软浮点函数__aeabi_flog2(输入x在r0,结果返回在r0) - 计算
y * log2(x):调用__aeabi_fmul(r0存第一个乘数,r1存第二个乘数,结果返回在r0) - 计算
2^(结果):调用你的pow2函数(假设输入在r0,结果返回在r0)
如果这部分逻辑缺失或者参数传递错误,r0就不会被更新为正确的幂运算结果,最后自然返回初始的x。
3. 分支处理的完整性
幂运算需要处理特殊分支:
- 当
y == 0时,返回1.0(x≠0的情况) - 当
y == 1时,直接返回x
如果这些分支的处理逻辑缺失,或者分支跳转错误,也会导致函数提前返回x。
修复后的示例代码
这里给你补全核心逻辑的示例,你可以参考调整:
.globl fpow fpow: stmfd sp!, {r4, r5, r6, lr} mov r4, r0 @ 保存输入的x mov r5, r1 @ 保存输入的y @ 分支1:y == 0时返回1.0 mov r0, r5 mov r1, #0 bl __aeabi_fcmpeq beq return_one @ 分支2:y == 1时返回x mov r0, r5 mov r1, #0x3F800000 @ float 1.0的二进制表示 bl __aeabi_fcmpeq beq return_x @ 核心幂运算:x^y = 2^(y * log2(x)) mov r0, r4 @ 传入x计算log2(x) bl __aeabi_flog2 mov r1, r5 @ 传入y作为乘法的第二个参数 bl __aeabi_fmul @ 得到y * log2(x) bl pow2 @ 计算2^z,得到最终结果 @ 恢复寄存器并返回 ldmfd sp!, {r4, r5, r6, pc} return_one: mov r0, #0x3F800000 @ 设置返回值为float 1.0 ldmfd sp!, {r4, r5, r6, pc} return_x: mov r0, r4 @ 返回原始的x ldmfd sp!, {r4, r5, r6, pc}
最后排查建议
- 检查你的
pow2函数是否正确实现,确保输入在r0时能返回正确的2^z结果 - 用调试工具跟踪寄存器变化,看
r0在每一步调用后是否被正确更新为中间结果
内容的提问来源于stack exchange,提问作者user6499716
相关产品推荐
相关产品推荐

