我发现很难找到在 Apple Silicon 上运行的良好、完整的汇编示例,特别是对于 SIMD 类型的操作,而不是不完整的、过于通用的片段。
出于我自己的好奇心,我想在 M2 机器上写一个例子......
- 采用一系列数字(首先内置于汇编文件中)
- 将它们累积为一个结果(使用 SIMD 指令)
- 将结果输出到 stdout
我有以下源代码,在一个名为test.s
...的文件中。
.global _start
.align 2
_start:
;;; Load numbers into x0
ldr x0, numbers
;;; Load elements from array in x0 into dedicated Neon register
ld1 { v0. 4s }, [x0]
;;; Accumulate elements in vector using dedicated Neon instruction
addv s0, v0.4s
;;; Prepare formatted string
adrp x0, format@page
add x0, x0, format@pageoff
;;; Add result to the stack for printing
str s0, [sp, #-16]!
;;; Print string
bl _printf
mov x16, #1
svc 0
numbers: .word 1, 2, 3, 4
format: .asciz "Answer: %u.\n"
...,使用以下命令进行组装和链接...
as -g -arch arm64 -o test.o test.s
ld -o test test.o -lSystem -syslibroot `xcrun -sdk macosx --show-sdk-path` -e _start -arch arm64
10
我本来期望在运行程序时得到答案,但我得到的却不是这个。
我做错了什么?
ldr x0, numbers
将从标记numbers
为的地址加载x0
(这只有效,因为numbers
恰好位于与指令足够近的地址,在同一部分中)。因此,中的值x0
将不是的地址numbers
,而是存储在那里的数据。您最终将x0
包含该值0x0000000200000001
,并且后续的内存访问可能会崩溃。您应该按照顺序将地址
numbers
放入,就像您对下面的操作一样。x0
adrp/add
format
而且,
st1
应该是ld1
,正如您已经提到的。将这些行更改为
使程序
10
为我打印正确的值。谢谢你们两位——在遵循
clang
Peter 的建议后,得到了一些有趣的结果。我从链接器收到以下对齐错误...
...,并且需要
.p2align 4, 0x0
数字,才能使其工作。有趣的是,从编译器的角度看,使用了
ldr q0, ...
Instead ofld1 { v0.4s }, ...
和addv.4s s0, v0
Instead ofaddv s0, v0.4s
。需要对对齐进行更多研究,尝试其他指令,并选择
x8
过度、x2
或x3
(也许避免参数寄存器?)。再次感谢您的帮助。