M1 Mac下Clang编译ARM64汇编调用log2函数出现段错误求助
问题分析与解决方案
针对你在M1 Mac ARM64架构下汇编调用libm的log2函数出现段错误的问题,核心原因集中在函数调用约定匹配和栈操作规范上,具体分析如下:
1. 函数符号与参数寄存器不匹配
Apple ARM64平台的libm中,浮点函数的命名和参数寄存器有明确区分:
- 单精度浮点版本:函数名为
_log2f,参数通过s0寄存器传递 - 双精度浮点版本:函数名为
_log2,参数通过d0寄存器传递
你的代码中用s0传递参数,却调用了双精度版本的_log2,函数会尝试从d0读取参数(实际是s0的高位垃圾数据),进而触发非法内存访问导致段错误。
2. 栈对齐违反ARM64调用约定
ARM64的AAPCS64规范要求:执行bl调用函数时,栈指针sp必须保持16字节对齐。如果你的代码在执行bl _log2前,sp未满足对齐要求,函数内部的栈操作会直接触发段错误。
比如,若当前栈帧未通过sub sp, sp, #xxx分配足够且对齐的空间,直接访问sp+224这类偏移后,sp本身可能不再是16字节对齐的状态。
3. 栈偏移合法性问题
你直接从sp+224加载参数、向sp+288存储结果,需要确保这些偏移完全在当前函数的栈帧范围内。如果函数开头未分配足够的栈空间(比如未执行sub sp, sp, #<足够大小>),访问这些地址会踩到栈外的非法内存,引发段错误。
修正示例代码
单精度版本(调用_log2f)
; 函数开头先分配足够且对齐的栈空间(示例分配304字节,确保sp对齐) sub sp, sp, #304 ; 加载单精度参数到s0 ldr s0, [sp, #224] ; 调用单精度log2函数 bl _log2f ; 存储单精度结果 str s0, [sp, #288] ; 函数结束释放栈空间 add sp, sp, #304 ret
双精度版本(调用_log2)
sub sp, sp, #304 ; 双精度参数用d0寄存器 ldr d0, [sp, #224] bl _log2 ; 双精度结果占8字节,确保偏移合理 str d0, [sp, #288] add sp, sp, #304 ret
额外验证建议
- 用
nm kernel.o查看目标文件中的符号引用,确认是否调用了正确的_log2或_log2f - 用
lldb调试共享库,在bl指令处设置断点,检查sp是否为16字节对齐,以及s0/d0寄存器的参数值是否正确
内容的提问来源于stack exchange,提问作者Steven Daniel Anderson
相关产品推荐
相关产品推荐

