I am trying to understand how to send more complicated values to and from Go ASM functions; beyond the typical uint in, uint out case. I stumbled upon a great example of this advanced usage in the crypto/elliptic
with the function p256BigToLittle in p256_asm_arm64.s
. It takes an byte slice and uint64 slice, it then processes the bytes and puts the output value into the uint64 slice. Below is the function with the preprocessor define statements substituted. Here are the main things I do not understand:
- I cannot find define statements for
res
orin
so are these being resolved at compile time from the function signature in the .go file? (IE: if I made a functionfunc myFunc(arg1 *int)
can I referencearg1
in the corresponding asm file?) - Where did the magic number
+24
inMOVD in+24(FP), R1
come from? - I am assuming the
1*16(R1)
is just meant to point to the second element of the in byte slice (8*2)? How do you know the spacing between elements of a slice? Ifin
were a uint32 slice would the second element be be1*64(R1)
? - Where is the Go Slice header during all of this? How is it being avoided?
// func p256BigToLittle(res []uint64, in []byte)
TEXT ·p256BigToLittle(SB),NOSPLIT,$0
MOVD res+0(FP), R0
MOVD in+24(FP), R1
LDP 0*16(R1), (R3, R4)
LDP 1*16(R1), (R5, R6)
REV R3, R3
REV R4, R4
REV R5, R5
REV R6, R6
STP (R6, R5), 0*16(R0)
STP (R4, R3), 1*16(R0)
RET