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系统调用的参数,传递顺序完全错误:
系统调用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)
你当前代码把路径地址放到
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
相关产品推荐
相关产品推荐

