【问题标题】:using value of external variables in assembly在汇编中使用外部变量的值
【发布时间】:2020-03-13 11:28:30
【问题描述】:

我在汇编中使用 .extern 变量时遇到了一些麻烦。我怎样才能将它们的值放入寄存器中?

.extern a, b, c
.global main

.text
main:
  mov *value of a*, %rax
    ret

我尝试了以下方法:

  1. 在 a 前添加符号:.a$aa[0]a[1]*a
  2. 试图将.extern 视为标签.extern+2 等'
  3. 也试过.extern a

我想我不太明白.extern 是什么意思以及如何访问它。我试过阅读英特尔的手册,但在网上找不到任何关于我需要什么的信息 - 我想我不知道如何正确地写我的问题,因为我不知道 .extern 是什么。

如果有人可以向我介绍有关它的信息以及如何使用它,我将不胜感激。

【问题讨论】:

    标签: assembly extern att


    【解决方案1】:

    mov a(%rip), %raxa 加载。

    mov a, %rax 也可以,但不要那样做;您总是需要 RIP-relative 或整数寄存器来寻址 x86-64 中的静态存储。)

    我认为您缺少的是 .extern 就像在 C++ 中一样:它声明符号是在不同的目标文件中定义的其他地方。因此,除非您与另一个 .o 链接,否则上述内容将组装但不会链接到可执行文件中,例如来自在 .c 的全局范围内编译 long a = 1;

    在 GAS 中 .extern 是无操作的,因为对于当前 asm 文件中未定义的符号名称已经假定了这一点。 See the manual


    也许您想在 .data 部分保留一些空间并在该空间上放置标签,就像 C 编译器在声明全局变量时所做的那样:

    long a;
    long main(){   // with int main GCC optimizes to loading only EAX
        return a;
    }
    

    使用 GCC -O2 (Godbolt) 编译为以下 asm,归结为您想要保留的手写版本的部分:

    main:
            mov     a(%rip), %rax
            ret
    
      .comm   a,8,8    # reserve 8 bytes in the BSS and call it  a
    

    如果我们使用long a = 1;(非零初始化器):

    .data             # switch to the .data section
    .globl  a         # declare a as externally visible, like a C global not static
    a:                          # a label declares a symbol with address = this position
            .quad   1           # a qword with integer value 1
    

    一般来说,如果您知道要查找什么,则可以从编译器输出中学习 asm 语法,并编译足够简单的 C 文件。 (How to remove "noise" from GCC/clang assembly output?) 但是如果你知道会发生什么,那么一些重要的部分(例如.section)主要是噪音,所以 Godbolt 将其过滤掉。要查看它,您还必须查看 .size.type 声明,作为初学者无需担心。

    【讨论】:

    • 非常感谢您提供的所有信息和帮助!我想我现在理解得更好了。您能否建议我如何打印寄存器的内容,以便我可以真正看到那里发生了什么?我尝试将存储在 %rsi 中的 %ebx 移动到 %rsi 并调用 syscall,但它不起作用
    • write 接受一个指向内存中字符串的指针。 strace 会告诉你,如果你传递一个整数值,你会得到 -EFAULT 的错误指针。您可以手动转换:Printing an integer as a string with AT&T syntax, with Linux system calls instead of printf。或者,也许您正在寻找 printf。 Calling printf in x86_64 using GNU assembler谷歌会告诉你这一点。或者查看 C 的编译器输出。
    猜你喜欢
    • 2021-05-03
    • 1970-01-01
    • 1970-01-01
    • 2021-12-17
    • 2012-07-20
    • 1970-01-01
    • 1970-01-01
    • 2020-02-14
    • 1970-01-01
    相关资源
    最近更新 更多