x64 上栈指针(rsp)不对齐引起的 segmentation fault, 以及 c 语言可变参数的一个细节

1. 现象

        最近在 macos 上写编译器时遇到一个异常,生成的目标文件执行时报 segmentation fault。 用 lldb 调试跟踪最终在 movaps %xmm0, -0xa0(%rbp) 指令时报错:

        stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)

2. 分析

        由上图可以看到是在调用 printf 函数时报错的,而操作 xmm0 xmm1 这些寄存器需要 rsp/rbp 16字节对齐,查看一下寄存器的值,果然是没有对齐。

        经过仔细检查最后发现是一个汇编写的内部函数中没有把 rsp 对齐,加一条 push 即可解决问题。在 Windows + VS2022 上做了同样的测试,结果正常没有报异常,原因是 VC 编译器的 printf 函数实现不同,没有一上来就将 xmm 寄存器入栈。

3. 意外发现

        在分析过程中发现调用 printf 函数之前 clang/gcc 编译器会写一条 mov al, #0 的指令:

        但是调用其它函数却没有,分析 printf 的汇编发现有一条 test al, al 指令判断 al 是否为 0,是刚跳转,不是则 xmm0 ~ xmm7 入栈。

        函数定义:int printf(const char * fmt, ...) ;  与普通函数声明相比也就是加了个不定参数,写一个函数测试一下看看,果然如此!

void func3(){
}
void func4(int a, ...){
}

        至于这个 al 寄存器在这里的具体用法去研究一下 gcc/llvm 再说,目前我的编译器先不支持这个操作,回头再写它的具体用法。

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值