I found an ARM64/MacOS "Hello, World" program that looks like this:
.global _main
.align 2
_main: mov X0, #1
adr X1, helloworld
mov X2, #13
mov X16, #4
svc 0
mov X0, #0
mov X16, #1
svc 0
helloworld: .ascii "Hello World!\n"
What I'd like to do is eliminate the hard-coded string-length (mov X2, #13
). But I can't figure out how to get as
to subtract two label values for use in an expression.
I tried adding helloend:
after the string and doing
mov X2, #helloend - helloworld
Which got me this message:
hello.s:6:9: error: unknown AArch64 fixup kind!
mov X2, #helloend - helloworld
I also tried doing a runtime subtraction, but trying to use =label
as a parameter to the sub
instruction gave me the same "error: unknown AArch64 fixup kind!" message.
I'm using the as
that's part of clang 14.0.3.
What's the solution?
You can create a new symbol with the length, then mov
it into a register.
len = helloend - helloworld
mov x2, #len
Or .equ len, helloend - helloworld
works too. You can shorten it a bit by defining it right after the string:
helloworld: .ascii "Hello World!\n"
len = . - helloworld
I think the issue is that with mov x2, #(end - begin)
, the assembler tries to emit fixups to have the linker do the subtraction and encode the result into the instruction. This isn't supported. But len = end - begin
forces the subtraction to be done within the assembler, and then it can encode the immediate directly.