【问题标题】:Combining c and assembler code结合 c 和汇编代码
【发布时间】:2014-12-13 22:44:41
【问题描述】:

这是我的 C 代码:

#include <stdio.h>

    void sum();
    int newAlphabet;
    int main(void)
    {
        sum();
        printf("%d\n",newAlphabet);
    }

这是我的汇编代码:

.globl _sum

_sum:
    movq $1, %rax
    movq %rax, _newAlphabet
    ret

我试图从我的主函数中调用 sum 函数,以将 newAlphabet 设置为 1,但是当我编译它(gcc -o test assembler.c assembler.s,在 64 位 OSX 笔记本电脑上编译)时,我得到以下信息错误:

x86-64 不支持 32 位绝对寻址 不能做有符号的 4 字节重定位 都是由“movq %rax, _newAlphabet”行引起的

我确定我犯了一个非常基本的错误。任何人都可以帮忙吗?提前致谢。

编辑:

以下是 C 代码翻译成汇编程序后的相关部分:

.comm   _newAlphabet,4,2
...
movq    _newAlphabet@GOTPCREL(%rip), %rax

【问题讨论】:

  • _newAlphabet在汇编器中的声明在哪里?另外,我很确定int 在 OSX 上是 32 位的(即使在 x86-64 中也是如此)。
  • 我可能错误地认为 c 代码中的 int newAlphabet 会被汇编程序识别。如果这是错误的,我该如何解决?我应该改用 movl 吗?
  • 如果我将 movl 或 mov 与 %eax 一起使用,我会遇到同样的错误
  • @SimonMeans:如果您尝试newAlphabet(即没有下划线)会怎样?如果这没有帮助,我建议编译一些简单的程序,使用带有-S 选项的这个外部变量来查看它的汇编指令(也就是说,识别这个变量是如何被引用的)。
  • stackoverflow.com/questions/25799551/… 我认为它可以用mov 指令回答你的问题(如果我没看错的话,似乎是重复的)。

标签: c macos gcc assembly x86-64


【解决方案1】:

Mac OS X 默认使用与位置无关的可执行文件,这意味着您的代码不能对变量使用常量全局地址。相反,您需要以与 IP 相关的方式访问全局变量。只需更改:

movq %rax, _newAlphabet

到:

mov %eax, _newAlphabet(%rip)

您将被设置(我从 64 位寄存器更改为 32 位寄存器以匹配 Mac OS X 上的 sizeof(int)。请注意,您还需要在某处使用 .globl _newAlphabet。这是我刚刚根据您的代码(注意我初始化了newAlphabet来证明它有效):

example.c:

#include <stdio.h>

void sum(void);
int newAlphabet = 2;
int main(void)
{
    printf("%d\n",newAlphabet);
    sum();
    printf("%d\n",newAlphabet);
    return 0;
}

程序集.s:

.globl _sum
.globl _newAlphabet

_sum:
    movl $1, _newAlphabet(%rip)
    ret

构建并运行:

$ cc -c -o example.o example.c
$ cc -c -o assembly.o assembly.s
$ cc -o example example.o assembly.o
$ ./example
2
1

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-05-07
    • 1970-01-01
    • 2011-08-27
    • 2013-02-14
    • 2012-03-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多