【问题标题】:I wrote x86-64 Assembly. But it's not working under Windows, only on OnlineGDB (Linux)我写了 x86-64 汇编。但它不能在 Windows 下工作,只能在 OnlineGDB (Linux) 上工作
【发布时间】:2020-06-03 08:52:42
【问题描述】:

我用汇编语言编写了一个 x86-64 代码。输出为 17。

    .text
.LC0:
    .string "%d\n"
printint:
    pushq   %rbp
    movq    %rsp, %rbp
    subq    $16, %rsp
    movl    %edi, -4(%rbp)
    movl    -4(%rbp), %eax
    movl    %eax, %esi
    leaq    .LC0(%rip), %rdi
    movl    $0, %eax
    call    printf@PLT
    nop
    leave
    ret

    .globl  main
    .type   main, @function
main:
    pushq   %rbp
    movq    %rsp, %rbp
    movq    $2, %r8
    movq    $3, %r9
    movq    $5, %r10
    imulq   %r9, %r10
    addq    %r8, %r10
    movq    $8, %r8
    movq    $3, %r9
    movq    %r8,%rax
    cqo
    idivq   %r9
    movq    %rax,%r8
    subq    %r10, %r8
    movq    %r10, %rdi
    call    printint
    movl    $0, %eax
    popq    %rbp
    ret

当我用 GCC 编译这个时,我得到了这个错误。

out.s: Assembler messages:
out.s:5: Error: bad register name `%rbp'
out.s:6: Error: bad register name `%rsp'
out.s:7: Error: bad register name `%rsp'
out.s:8: Error: bad register name `%rbp)'
out.s:9: Error: bad register name `%rbp)'
out.s:11: Error: bad register name `%rip)'
out.s:19: Warning: .type pseudo-op used outside of .def/.endef: ignored.
out.s:19: Error: junk at end of line, first unrecognized character is `m'
out.s:21: Error: bad register name `%rbp'
out.s:22: Error: bad register name `%rsp'
out.s:23: Error: bad register name `%r8'
out.s:24: Error: bad register name `%r9'
out.s:25: Error: bad register name `%r10'
out.s:26: Error: bad register name `%r9'
out.s:27: Error: bad register name `%r8'
out.s:28: Error: bad register name `%r8'
out.s:29: Error: bad register name `%r9'
out.s:30: Error: bad register name `%r8'
out.s:31: Error: `cqo' is only supported in 64-bit mode
out.s:32: Error: bad register name `%r9'
out.s:33: Error: bad register name `%rax'
out.s:34: Error: bad register name `%r10'
out.s:35: Error: bad register name `%r10'
out.s:38: Error: bad register name `%rbp'

同样,当我在 NASM 中执行此操作时,我收到以下错误。

out.s:1: warning: label alone on a line without a colon might be in error [-w+orphan-labels]
out.s:3: error: parser: instruction expected
out.s:5: error: parser: instruction expected
out.s:6: error: expression syntax error
out.s:7: error: parser: instruction expected
out.s:8: error: parser: instruction expected
out.s:9: error: parser: instruction expected
out.s:10: error: parser: instruction expected
out.s:11: error: parser: instruction expected
out.s:12: error: parser: instruction expected
out.s:18: error: parser: instruction expected
out.s:19: error: parser: instruction expected
out.s:21: error: label `pushq' inconsistently redefined
out.s:5: note: label `pushq' originally defined here
out.s:21: error: parser: instruction expected
out.s:22: error: expression syntax error
out.s:23: error: expression syntax error
out.s:24: error: expression syntax error
out.s:25: error: expression syntax error
out.s:26: error: parser: instruction expected
out.s:27: error: parser: instruction expected
out.s:28: error: expression syntax error
out.s:29: error: expression syntax error
out.s:30: error: expression syntax error
out.s:32: error: parser: instruction expected
out.s:33: error: expression syntax error
out.s:34: error: label `subq' inconsistently redefined
out.s:7: note: label `subq' originally defined here
out.s:34: error: parser: instruction expected
out.s:35: error: expression syntax error
out.s:37: error: label `movl' inconsistently redefined
out.s:8: note: label `movl' originally defined here
out.s:37: error: parser: instruction expected
out.s:38: error: parser: instruction expected

但是当我去https://www.onlinegdb.com/online_gcc_assembler编译它时,我得到了正确答案(17)。

我还在学习汇编语言。我搜索了一个答案,但找不到答案。你能解释一下这个原因吗?

关于我的笔记本电脑的详细信息

AMD RYZEN 5 处理器(基于 x64)

64 位 Windows 10

【问题讨论】:

  • 你标记了这个 NASM,但那是 GAS AT&T 语法。 NASM 使用 Intel 语法。你用什么命令来尝试组装它?
  • 你在本地使用的是哪个 GCC?运行gcc -dumpmachine 会得到什么?
  • @Michael mingw32 :|
  • @PeterCordes 我只用过 nasm out.s (out.s 是一个汇编文件)
  • @LasanNishshanka:那更糟; NASM 的默认输出格式是 16 位平面二进制。但是无论如何,除非您使用 NASM 指令将其完全重写为 Intel 语法,否则您不能使用 NASM 来组装它。当然,无论如何您都必须重写大部分指令才能将其移植到 Windows。可能从 Windows 的 C 编译器输出而不是 GNU/Linux 重新开始。 (您的代码显然是经过手动调整的 GCC 输出。)

标签: assembly gcc compilation x86-64 nasm


【解决方案1】:

out.s:31: Error: 'cqo' is only supported in 64-bit mode 告诉您您尝试在 32 位模式下组装此 64 位代码。也许您尝试在 Windows 下使用 mingw32,而不是 64 位 mingw?

此代码适用于 x86-64 GNU/Linux:请注意在 RDI、RSI 中传递参数的调用约定以及 @plt 的使用。 DLL 不使用 PLT,这是 GNU/Linux 的东西(传统的动态链接,而不是早期而不是惰性绑定的新样式 gcc -fno-plt)。这就是它在使用 x86-64 GNU/Linux 的 OnlineGDB 中工作的原因。

它不能在 64 位 Windows 下运行,WSL 除外。甚至 Cygwin 64 也是源兼容层,而不是二进制/ABI/调用约定。


此外,它是用带有 GAS 指令的 AT&T 语法编写的。 NASM 使用带有不同指令的 Intel 语法;难怪当你尝试用nasm -fwin64 组装它时,几乎每一行都是错误的。

【讨论】:

    猜你喜欢
    • 2020-03-01
    • 2021-01-26
    • 2021-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-16
    • 1970-01-01
    相关资源
    最近更新 更多