【问题标题】:GAS aarch64 syntax to get .ascii string lengthGAS aarch64 语法获取 .ascii 字符串长度
【发布时间】:2021-01-19 02:18:43
【问题描述】:

我正在尝试翻译这个x86_64 程序:

# 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

进入aarch64 程序:

// 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

但是,当我尝试组装上述程序时,我得到了这个错误:

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

我认为这有点像红鲱鱼,因为如果我改变这条线:

.equ MSG_LEN, . - MSG

进入这个:

.equ MSG_LEN, 13

然后它工作正常。但是我对这个解决方案不满意,因为我不想硬编码MSG_LEN,我希望汇编器能够像x86_64 版本一样在汇编时确定长度。你能帮我弄清楚如何在程序的aarch64 版本中设置MSG_LEN,而不必显式地硬编码一个值吗?

其他细节:我正在一个 Docker 容器内编译和运行这些程序,该容器是从这个 Dockerfile 构建的:

FROM ubuntu:20.04

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

我正在编译和运行x86_64 程序:

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

我正在编译和运行aarch64 程序:

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

【问题讨论】:

  • 您似乎使用的是 clang 而不是 gnu 汇编程序。 gnu assembler v2.25.1 代码没有问题。
  • @Jester 是的,clang 有自己的“集成汇编器”,但它被认为是 GAS 的替代品,就像 clang 是 gcc 的替代品一样。我一直在使用 clang 汇编器,同时学习了一堆不同的 GAS 教程和示例,并且在编译或运行任何东西时都没有遇到任何问题。
  • 抱歉,我无法使用 clang 进行测试,但代码似乎适合 gas。按预期生成d28001a2 mov x2, #0xd。
  • 我可以用 clang 重现错误。我认为这是 clang 汇编器中的一个错误。
  • .equ SYS_EXIT, 93 - 不要自己定义这些; #include <sys/syscall.h> 或 <asm/unistd.h> 使用 glibc / Linux 对 SYS_exit 或 __NR_exit 的定义(分别)。使用 gcc 或 clang 构建 .S 文件将在组装之前通过 C 预处理器运行它。 (而且这些头文件不包含任何 C 原型或任何东西,只是 #define 和 #if 的东西,所以它们与 asm 兼容。)

标签: assembly clang x86-64 arm64 gnu-assembler


【解决方案1】:

解决方案:我需要使用 -fno-integrated-as 和 clang 来告诉它直接使用 GNU Assembler 而不是它自己的内置集成汇编器(假设是一个插件替代 GAS,但显然不是)。我使用以下更新的命令编译并运行我的aarch64 程序没有问题:

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

感谢 @Jester 和 @Nate Eldredge 帮助我在 cmets 中进行调试。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多