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

Mac平台x86-64汇编syscall错误检查失效问题排查

macOS x86-64汇编syscall错误检查问题分析

问题描述

我在Mac平台编写x86-64汇编代码,通过syscall获取当前时间,原本运行正常。添加错误检查时,反汇编了gettimeofday包装函数,发现它在syscall后用jae指令处理成功结果——查资料知道jae是jnc的别名,于是我用jc指令做错误检查(进位标志置位则跳转到错误逻辑)。但出现异常:

  • 第二次执行syscall时进位标志被置位,但仍成功获取了新时间;
  • 添加将当前时间加5秒存入rdx的代码后,syscall后的jc会触发错误跳转,此时rax值为0xe(15),但curtime(%rip)仍正常更新。

想知道哪里出错了,为什么mov和add指令会影响错误检查?

反汇编的gettimeofday包装函数

___gettimeofday:
    4969:   48 c7 c2 00 00 00 00    movq    $0x0, %rdx
    4970:   b8 74 00 00 02  movl    $0x2000074, %eax
    4975:   49 89 ca    movq    %rcx, %r10
    4978:   0f 05   syscall
    497a:   73 08   jae 0x4984
    497c:   48 89 c7    movq    %rax, %rdi
    497f:   e9 41 d8 ff ff  jmp _cerror_nocancel
    4984:   48 83 f8 00 cmpq    $0x0, %rax
    4988:   74 08   je  0x4992
    498a:   48 89 07    movq    %rax, (%rdi)
    498d:   89 57 08    movl    %edx, 0x8(%rdi)
    4990:   31 c0   xorl    %eax, %eax
    4992:   c3  retq

问题复现代码

# get current time
    movq $0x2000074, %rax
    leaq curtime(%rip), %rdi
    syscall
    jc error

    # get current time again
    movq $0x2000074, %rax
    leaq curtime(%rip), %rdi
    syscall
    jc error

    # add 5 seconds to the start time and stash in rdx
    movq curtime(%rip), %rdx
    addq $5, %rdx

    movq $0x2000074, %rax
    leaq curtime(%rip), %rdi
    syscall
    jc error

问题原因

你忽略了macOS x86-64 syscall的两个核心调用约定,导致错误标志位异常:

  1. 未正确设置rdx寄存器
    gettimeofday的第二个参数是时区指针,通常传NULL(0)。你的代码前两次调用时rdx是未初始化的随机值,虽然内核可能容错处理,但会导致标志位状态不可预测;第三次调用时,你把rdx设置成了加5后的时间值(无效指针),内核检测到参数非法,返回错误码0xe(EFAULT地址错误)并置位CF。但内核已经完成了第一个参数(时间结构)的写入,所以curtime(%rip)仍能正常更新。

  2. 未保存rcx到r10
    macOS的syscall指令会将当前用户态RIP存入rcx,内核需要这个值来正确返回用户态,因此要求调用前必须把rcx的值移动到r10。你的代码跳过了这一步,导致内核返回逻辑破坏标志位,出现第二次调用CF置位但实际成功的异常情况。

解决方法

严格按照macOS syscall约定准备寄存器,修改后的代码如下:

# get current time
    movq $0x2000074, %rax
    leaq curtime(%rip), %rdi
    movq $0, %rdx          # 第二个参数传NULL
    movq %rcx, %r10        # 保存rcx到r10,符合macOS syscall约定
    syscall
    jc error

    # get current time again
    movq $0x2000074, %rax
    leaq curtime(%rip), %rdi
    movq $0, %rdx
    movq %rcx, %r10
    syscall
    jc error

    # add 5 seconds to the start time and stash in rdx
    movq curtime(%rip), %rdx
    addq $5, %rdx

    movq $0x2000074, %rax
    leaq curtime(%rip), %rdi
    movq $0, %rdx          # 重新设置rdx为NULL,覆盖之前的时间值
    movq %rcx, %r10
    syscall
    jc error

额外说明:macOS syscall成功时CF清零,失败时CF置位且rax返回错误码,jae/jnc判断成功分支是正确的,但必须严格遵守寄存器约定,否则标志位和返回值都会出现异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 02:55:23