pretzelhammer
pretzelhammer

Reputation: 15115

GAS aarch64 syntax to get .ascii string length

I'm trying to translate this x86_64 program:

# hello_world.s
# GNU Assembly, x86_64 Linux

.global _start

.data

.equ SYS_EXIT, 60
.equ SYS_WRITE, 1
.equ STDOUT, 1
.equ SUCCESS, 0

MSG:
    .ascii "Hello world!\n"

.equ MSG_LEN, . - MSG

.text

_start:
    # write(STDOUT, MSG, MSG_LEN)
    mov $SYS_WRITE, %rax
    mov $STDOUT, %rdi
    mov $MSG, %rsi
    mov $MSG_LEN, %rdx
    syscall

    # exit(SUCCESS)
    mov $SYS_EXIT, %rax
    mov $SUCCESS, %rdi
    syscall

Into an aarch64 program:

// hello_world.s
// GNU Assembly, aarch64 Linux

.data

.equ SYS_EXIT, 93
.equ SYS_WRITE, 64
.equ STDOUT, 1
.equ SUCCESS, 0

MSG:
    .ascii "Hello world!\n"

.equ MSG_LEN, . - MSG

.text

.global _start

_start:
    // write(STDOUT, MSG, MSG_LEN)
    mov x8, #SYS_WRITE
    mov x0, #STDOUT
    adr x1, MSG
    mov x2, #MSG_LEN
    svc #0

    // exit(SUCCESS)
    mov x8, #SYS_EXIT
    mov x0, #SUCCESS
    svc #0

However when I try to assemble the above program I get this error:

hello_world.s:27:13: error: expected compatible register or logical immediate
    mov x2, #MSG_LEN
            ^

Which I think is somewhat of a red herring because if I change this line:

.equ MSG_LEN, . - MSG

Into this:

.equ MSG_LEN, 13

Then it works fine. However I'm not happy with this solution because I don't want to hardcode the MSG_LEN, I want the assembler to be able to determine the length at assemble time like in the x86_64 version. Can you help me figure out how I can set MSG_LEN in the aarch64 version of the program without having to explicitly hardcode a value?

Additional details: I'm compiling and running these programs inside of a docker container which is built from this Dockerfile:

FROM ubuntu:20.04

RUN apt-get update
RUN apt-get -y install clang qemu qemu-system gcc-aarch64-linux-gnu

I'm compiling and running the x86_64 program with:

clang -nostdlib -target x86_64-linux-gnu -s hello_world.s -o hello_world.out && ./hello_world.out

And I'm compiling and running the aarch64 program with:

clang -nostdlib -target aarch64-linux-gnu -s hello_world.s -o hello_world.out && ./hello_world.out

Upvotes: 3

Views: 1753

Answers (1)

pretzelhammer
pretzelhammer

Reputation: 15115

Solution: I needed to use -fno-integrated-as with clang to tell it to use GNU Assembler directly instead of its own built-in integrated assembler (which is suppose to be a drop-in replacement for GAS but apparently it's not). I used the following updated command to compile and run my aarch64 program without issue:

clang -nostdlib -fno-integrated-as -target aarch64-linux-gnu -s hello_world.s -o hello_world.out && ./hello_world.out

Thanks to @Jester and @Nate Eldredge who helped me debug in the comments.

Upvotes: 3

Related Questions