我发现很难找到在 Apple Silicon 上运行的良好、完整的汇编示例,特别是 SIMD 类型的操作,而不是不完整、过于通用的片段。
出于我自己的好奇心,我想在 M2 机器上编写一个示例......
我有以下源代码,位于名为
test.s
... 的文件中
.global _start
.align 2
_start:
;;; Load numbers into x0
ldr x0, numbers
;;; Load elements from array in x0 into dedicated Neon register
st1 { 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
,正如您已经提到的。
将这些行更改为
adrp x0, numbers@page
add x0, x0, numbers@pageoff
ld1 { v0.4s }, [x0]
使程序为我打印正确的值
10
。