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

Mac M1下ARM汇编数字打印实现及学习资源求助

问题解答

1. Mac M1 ARM汇编实现数字打印

你的代码目前直接输出固定字符串,要实现数字打印,需要先将整数转换为ASCII字符串,再通过write系统调用输出。因为你使用的是无libc的纯系统调用方式(_start入口而非main),无法直接调用printf(会有链接依赖问题),所以需要手动实现整数转字符串逻辑。

修改后的完整代码

.global _start
.align 2

_start:
mov w5, #0

loop:
    mov w3, #15
    sdiv w6, w5, w3
    mul w6, w6, w3
    sub w6, w5, w6 
    cmp w6, #0
    b.eq _print_fizzbuzz
    
    mov w3, #3
    sdiv w6, w5, w3
    mul w6, w6, w3
    sub w6, w5, w6 
    cmp w6, #0
    b.eq _print_fizz
    
    mov w3, #5
    sdiv w6, w5, w3
    mul w6, w6, w3
    sub w6, w5, w6 
    cmp w6, #0
    b.eq _print_buzz 
    
    b _print_number

comparison:
    cmp w5, #50
    add w5, w5, #1
    b.ne loop
    
    mov x0, #0   // return 0
    mov x16, #1  // terminate syscall
    svc 0x80

_print_fizzbuzz:
mov x0, #1
adrp x1, fb@page
add x1, x1, fb@pageoff
mov x2, #9
mov x16, #4
svc 0
b comparison

_print_fizz:
mov x0, #1
adrp x1, fizz@page
add x1, x1, fizz@pageoff
mov x2, #5
mov x16, #4
svc 0
b comparison

_print_buzz:
mov x0, #1
adrp x1, buzz@page
add x1, x1, buzz@pageoff
mov x2, #5
mov x16, #4
svc 0
b comparison

_print_number:
// 将w5中的整数转换为ASCII字符串存入num_buf
mov w0, w5          // 传入要转换的数字
adrp x1, num_buf@page
add x1, x1, num_buf@pageoff
bl _int_to_ascii

// 计算字符串长度(从num_buf到末尾的换行符)
adrp x2, num_buf@page
add x2, x2, num_buf@pageoff
sub x2, x1, x2      // x1现在指向换行符的下一位,减去起始地址得到长度
mov x0, #1          // 标准输出fd
adrp x1, num_buf@page
add x1, x1, num_buf@pageoff
mov x16, #4         // write syscall
svc 0
b comparison

// 整数转ASCII字符串函数
// 输入: w0 = 要转换的正整数, x1 = 缓冲区起始地址
// 输出: x1 = 字符串末尾的下一位地址
_int_to_ascii:
mov w2, #10         // 除数10
mov x3, x1          // 保存缓冲区起始地址

// 处理0的特殊情况
cmp w0, #0
b.ne _int_to_ascii_loop
mov w4, #'0'
strb w4, [x1], #1
b _add_newline

_int_to_ascii_loop:
cmp w0, #0
b.eq _reverse_string

udiv w4, w0, w2     // 商存入w4
msub w5, w4, w2, w0 // 余数 = w0 - w4*10,存入w5
add w5, w5, #'0'    // 余数转ASCII
strb w5, [x1], #1   // 存入缓冲区,指针后移
mov w0, w4          // 商作为下一次的被除数
b _int_to_ascii_loop

_reverse_string:
sub x1, x1, #1      // 回退到最后一个有效字符
_reverse_loop:
cmp x3, x1
b.ge _add_newline

ldrb w4, [x3]
ldrb w5, [x1]
strb w5, [x3]
strb w4, [x1]

add x3, x3, #1
sub x1, x1, #1
b _reverse_loop

_add_newline:
mov w4, #'\n'
strb w4, [x1], #1
ret

.data
fb: .asciz "FizzBuzz\n"
fizz: .asciz "Fizz\n"
buzz: .asciz "Buzz\n"
num_buf: .space 10  // 足够存储0-50的字符串加换行符

关键逻辑说明

  • 整数转ASCII:通过循环对10取余得到每一位数字,转成ASCII后存入缓冲区,再反转字符串(因为取余得到的是从个位到高位的顺序)。
  • 缓冲区处理:在.data段定义num_buf作为临时存储,长度10足够容纳0-50的字符串加换行符。
  • 系统调用:转换完成后,计算字符串长度,调用write系统输出。

编译运行命令

编译用clang:

clang -o fizzbuzz fizzbuzz.s -nostdlib

运行:

./fizzbuzz

2. Mac ARM汇编学习资源推荐

  • Apple官方ARM64编程指南:Apple开发者文档中包含ARM64汇编语法、系统调用规范、macOS平台特有的汇编注意事项,是最权威的参考。
  • 《ARM64 Assembly Language Programming with Raspberry Pi and Mobile Devices》:虽然以树莓派为载体,但ARM64的核心指令集、编程逻辑通用,适合入门后深入理解体系结构。
  • macOS系统调用手册:在终端执行man 2 syscall或man syscalls,可以查看macOS支持的所有系统调用编号、参数要求,这是纯系统调用编程的必备参考。
  • LLVM汇编器文档:macOS默认使用LLVM的as汇编器,其ARM64语法与GNU汇编有细微差异,可查看LLVM官方的ARM64汇编语法说明。
  • 开源项目代码:查看Coreutils、Homebrew等开源工具的ARM64架构实现代码,学习实际场景下的macOS汇编编程技巧。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 02:15:16