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
相关产品推荐
相关产品推荐

