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

ARMv8平台Syscall 56调用失败:无法打开Xbox游戏手柄/dev/input/js0

问题

我尝试用Syscall 56打开路径/dev/input/js0的Xbox手柄,已经用C语言的open()程序验证设备存在,但汇编程序始终跳转到FailExit分支。

汇编代码如下:

.global main

.section .text
.align 2
main:
    ldr x0, =GamepadPath
    mov x1, #0
    mov x8, #56
    svc #0

    cmp x0, #0
    blt FailExit 

    mov x0, #1
    ldr x1, =SuccessMsg
    mov x2, #25
    mov x8, #64
    svc #0 

    mov x0, #0
    mov x8, #93
    svc #0

FailExit:
    mov x0, #1
    ldr x1, =ErrorMsg
    mov x2, #25
    mov x8, #64
    svc #0
    mov x0, #0
    mov x8, #93
    svc #0

.section .data

.section .rodata
GamepadPath: .asciz "/dev/input/js0"
SuccessMsg: .asciz "Gamepad Connected\n\n"
ErrorMsg: .asciz "Gamepad Not Available\n\n"

.section .bss

我查阅了openat(2)手册、ARM64系统调用相关资料,困惑的是Syscall 56(openat)的第一个参数x0应该是open系统调用的返回值?但ARMv8 Linux相关参考里找不到对应说明。

分析与解决

核心问题是误用openat系统调用的参数,传递顺序完全错误:

  1. 系统调用56对应openat,原型为:

    int openat(int dirfd, const char *pathname, int flags, mode_t mode);
    

    ARM64 Linux下参数映射:

    • x0: 目录文件描述符dirfd(模拟普通open行为时,需传入AT_FDCWD,值为-100,即十六进制0xFFFFFF9C)
    • x1: 路径字符串地址(即代码中的GamepadPath)
    • x2: 打开标志flags(只读打开传0即可)
    • x3: 文件权限mode(仅创建文件时需要,这里传0)
  2. 你当前代码把路径地址放到x0(对应openat的dirfd参数),把flags放到x1,完全不符合openat的参数要求,导致系统调用返回错误(负数),进而跳转到FailExit。

修正后的代码

有两种修正方式:

方式一:正确使用openat系统调用

.global main

.section .text
.align 2
main:
    mov x0, #0xFFFFFF9C  @ 传入AT_FDCWD,对应-100
    ldr x1, =GamepadPath @ 路径地址放到x1
    mov x2, #0           @ O_RDONLY标志
    mov x3, #0           @ 权限,此处不需要
    mov x8, #56          @ openat的系统调用号
    svc #0

    cmp x0, #0
    blt FailExit 

    mov x0, #1
    ldr x1, =SuccessMsg
    mov x2, #25
    mov x8, #64
    svc #0 

    mov x0, #0
    mov x8, #93
    svc #0

FailExit:
    mov x0, #1
    ldr x1, =ErrorMsg
    mov x2, #25
    mov x8, #64
    svc #0
    mov x0, #0
    mov x8, #93
    svc #0

.section .data

.section .rodata
GamepadPath: .asciz "/dev/input/js0"
SuccessMsg: .asciz "Gamepad Connected\n\n"
ErrorMsg: .asciz "Gamepad Not Available\n\n"

.section .bss

方式二:直接使用open系统调用

ARM64下open的系统调用号是5,参数顺序和C语言open一致,更贴合你最初的代码逻辑:

.global main

.section .text
.align 2
main:
    ldr x0, =GamepadPath @ 路径地址
    mov x1, #0           @ O_RDONLY标志
    mov x2, #0           @ 权限
    mov x8, #5           @ open的系统调用号
    svc #0

    cmp x0, #0
    blt FailExit 

    mov x0, #1
    ldr x1, =SuccessMsg
    mov x2, #25
    mov x8, #64
    svc #0 

    mov x0, #0
    mov x8, #93
    svc #0

FailExit:
    mov x0, #1
    ldr x1, =ErrorMsg
    mov x2, #25
    mov x8, #64
    svc #0
    mov x0, #0
    mov x8, #93
    svc #0

.section .data

.section .rodata
GamepadPath: .asciz "/dev/input/js0"
SuccessMsg: .asciz "Gamepad Connected\n\n"
ErrorMsg: .asciz "Gamepad Not Available\n\n"

.section .bss

补充说明

你之前对openat参数的理解完全错误:openat的第一个参数dirfd是用来指定相对路径的基准目录的文件描述符,和open的返回值没有任何关系。当传入AT_FDCWD时,openat等价于普通的open调用,使用当前工作目录作为基准。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 22:14:51