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

AArch64汇编代码无法读取标准输入(stdin)求助

环境信息

条目信息
计算机MacBook 2022 M2 13英寸 24GB
操作系统MacOS 15.1 Beta 2405055e
编译命令as hello.s -g -o hello.o && ld -o hello.exec hello.o -lSystem -syslibroot $(xcrun -sdk macosx --show-sdk-path) -e _start -arch arm64

问题描述

我是汇编完全新手,正在学习Mach-O系统的AArch64汇编。以下是我的代码:

.global _start
.align 4

_start: mov X0, #0
    adr X1, buffer
    mov X2, #128
    mov X16, 3
    svc #0x80

    mov X0, #1
    adr X1, buffer
    mov X2, #128
    mov X16, 4
    svc #0x80

    mov X0, #0
    mov X16, 1
    svc #0x80

buffer: .skip 128

代码无法正常工作,shell操作过程如下(test是我输入的内容):

(base) -----------------------------------------------------------------------------------
╭─ makabaka1880@Makabakas-MacBookPro.local 
╰─  ./helloworld.exec                                            [17:23] 127 ~/ASM
test
(base) -----------------------------------------------------------------------------------
╭─ makabaka1880@Makabakas-MacBookPro.local 
╰─  est                                                            [17:26] 0 ~/ASM
zsh: command not found: est

通过lldb调试发现,执行mov X2, #128后,X1指向的buffer内存区域为空:

(lldb) memory read -s1 -fu -c128 0x00000001003b7f24 --force
0x1003b7f24: 0
0x1003b7f25: 0
0x1003b7f26: 0
0x1003b7f27: 0
0x1003b7f28: 0
0x1003b7f29: 0
0x1003b7f2a: 0
0x1003b7f2b: 0
0x1003b7f2c: 0
0x1003b7f2d: 0
...

问题原因

  1. Syscall编号错误:你使用的3(read)、4(write)、1(exit)是x86_64架构的syscall编号,MacOS AArch64架构下的syscall需要加上0x2000000前缀,正确编号为:

    • read: 0x2000003
    • write: 0x2000004
    • exit: 0x2000001
      错误的编号会导致内核无法识别请求,读取操作直接失败。
  2. 输入未被程序捕获:由于syscall调用失败,程序没有读取到输入内容,输入的test\n直接被shell接收,shell解析时出现了est命令找不到的错误。

  3. 编译命令笔误:原命令中多写了一个as,会导致编译失败。


修正方案

修正后的汇编代码

.global _start
.align 4

_start:
    // 读取标准输入到buffer,最多128字节
    mov     X0, #0                  // 文件描述符:标准输入
    adr     X1, buffer              // 缓冲区地址
    mov     X2, #128                // 最大读取字节数
    mov     X16, #0x2000003         // AArch64 syscall: read
    svc     #0x80

    // 写入标准输出,使用read返回的实际字节数
    mov     X2, X0                  // 将read返回的实际读取字节数传给write
    mov     X0, #1                  // 文件描述符:标准输出
    adr     X1, buffer              // 缓冲区地址
    mov     X16, #0x2000004         // AArch64 syscall: write
    svc     #0x80

    // 退出程序,返回码0
    mov     X0, #0                  // 退出状态码
    mov     X16, #0x2000001         // AArch64 syscall: exit
    svc     #0x80

buffer: .skip 128

修正后的编译命令

as hello.s -g -o hello.o && ld -o hello.exec hello.o -lSystem -syslibroot $(xcrun -sdk macosx --show-sdk-path) -e _start -arch arm64

额外说明

  • MacOS AArch64的syscall必须加上0x2000000前缀,这是系统规定的偏移量,用于区分不同类型的系统调用。
  • read调用完成后,X0寄存器会返回实际读取的字节数(包括输入的换行符),将其传给write的X2参数,可以避免输出多余的空字节。
  • 若仍有问题,可在lldb中查看syscall返回值(X0),负数表示调用失败,对应MacOS的错误码。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 23:50:01