【问题标题】:gcc compilation and assemblyinggcc 编译和组装
【发布时间】:2013-02-10 11:23:52
【问题描述】:

我正在尝试使用 gcc 创建一个可执行文件。我有两个文件 virtualstack.c(它由下面的 C 代码组成)和 stack.s,它由用 AT&T 语法编写的 intel x86 汇编代码组成(见下面的 C 代码)。我的命令行命令是gcc -c virtualstack.c -s stack.s,但出现两个错误(stack.s 中的第 3 行)-missing symbol name in directiveno such instruction _stack_create。我以为我已经在程序集中正确声明了 C 中的函数,前缀为下划线 (_)。我会非常感谢任何 cmets。

C 代码:

#include <stdio.h>
#include <stdlib.h>

extern void stack_create(void);

int main(void)
{
stack_create();

return 0;
}

汇编代码:

.global _stack_create
    .type, @function

_stack_create
pushl   %ebp
movl    $5, %esp
movl    %esp, ebp
movl    $21, %edx
pushl   %edx

【问题讨论】:

  • 第二个_stack_create 后面需要一个冒号。而且我不知道.type 的行是否正确,但这不是必需的。顺便说一句,将 5 移动到 esp 是自找麻烦。
  • @alexey frunze。谢谢:) 现在我对结肠感到愚蠢。我应该看到那个。没有 .type 它编译。我仍然需要看看它是否可执行。也感谢 esp 警告。
  • 好吧。我已经删除了 .type、@function。我发现 gcc 创建了单独的对象文件。我尝试改写 gcc -o vs virtualstack.c -s stack.s 。我认为应该创建一个 vs.out 文件(可执行文件)。然后我在 main() 中得到了对 stack_create 的未定义引用 - 知道为什么吗?
  • -s 是干什么用的?没有它应该可以工作。
  • 您的汇编代码完全错误。它会破坏堆栈指针(通过将 5 写入其中),如果 pushl %edx 本身不会导致异常(因为通常,地址 0 周围的内存不可访问)然后它会导致 CPU 执行 @987654332 后面的任何垃圾@在内存中。

标签: gcc assembly compilation x86


【解决方案1】:

我将尝试向您解释如何调查此类案件。

1) 让编译器为您工作总是一个好主意。所以让我们从代码开始(我们称之为 assemble.c):

    #include <stdio.h>
    #include <stdlib.h>

    /* stub stuff */
    void __attribute__ ((noinline))
    stack_create(void) { }

    int
    main(void)
    {
      stack_create();
      return 0;
    }

现在使用gcc -S -g0 assemble.c 将其编译为汇编程序。 stack_create 函数被组装成(你的结果可能会有所不同,所以请自行按照我的说明进行操作):

  .text
  .globl  stack_create
  .type stack_create, @function
stack_create:
  pushq %rbp
  movq  %rsp, %rbp
  popq  %rbp
  ret
  .size stack_create, .-stack_create

2) 现在你只需要使用这个模板并用你的东西填充它:

  .text
  .globl  stack_create
  .type stack_create, @function
stack_create:
  pushq %rbp
  movq  %rsp, %rbp

  ;; Go and put your favorite stuff here!
  pushl   %ebp
  movl    $5, %esp
  movl    %esp, ebp
  movl    $21, %edx
  pushl   %edx
  ... etc ...

  popq  %rbp
  ret
  .size stack_create, .-stack_create

当然,还要将其分开 .s 文件,比如 stack.s。

3) 现在让我们一起编译。从 assemble.c 中删除存根内容并将所有内容编译为:

gcc assemble.c stack.s

我没有错误。我相信你也不会出错。

主要教训:永远不要尝试在汇编器中编写诸如节、函数标签等细节。编译器更好地知道如何去做。用他的知识代替。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-01-30
    • 1970-01-01
    • 1970-01-01
    • 2018-05-02
    • 1970-01-01
    • 1970-01-01
    • 2013-12-27
    相关资源
    最近更新 更多