难以理解编译器和汇编语言如何组合在一起

时间:2019-07-17 05:28:20

标签: assembly

这更多是一个概念性问题,但是我正在为即将进行的项目学习嵌入式系统。我一直在浏览有关教程的教程。

https://www.tutorialspoint.com/embedded_systems/es_tools.htm

此网页讨论编译器,汇编器和耦合。

基本上:汇编过程如何与编译器一起工作。我在哪里以及如何分割这些信息?我没有得到什么?

1 个答案:

答案 0 :(得分:1)

使用gnu工具自己尝试

#define FIVE 5

extern unsigned int more_fun ( unsigned int );
unsigned int fun ( void )
{
    return(more_fun(FIVE)+1);
}

保存临时文件gcc首先需要进行预处理以引入包含并替换定义/宏

# 1 "so.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "so.c"




extern unsigned int more_fun ( unsigned int );
unsigned int fun ( void )
{
    return(more_fun(5)+1);
}
被送入实际编译器的

,gcc程序不是编译器,而是一个调用其他程序的程序。编译器输出是汇编语言

    .arch armv5t
    .fpu softvfp
    .eabi_attribute 20, 1
    .eabi_attribute 21, 1
    .eabi_attribute 23, 3
    .eabi_attribute 24, 1
    .eabi_attribute 25, 1
    .eabi_attribute 26, 2
    .eabi_attribute 30, 2
    .eabi_attribute 34, 0
    .eabi_attribute 18, 4
    .file   "so.c"
    .text
    .align  2
    .global fun
    .syntax unified
    .arm
    .type   fun, %function
fun:
    @ args = 0, pretend = 0, frame = 0
    @ frame_needed = 0, uses_anonymous_args = 0
    push    {r4, lr}
    mov r0, #5
    bl  more_fun
    add r0, r0, #1
    pop {r4, pc}
    .size   fun, .-fun
    .ident  "GCC: (Ubuntu/Linaro 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609"
    .section    .note.GNU-stack,"",%progbits
然后

gcc调用汇编程序以将其汇编为一个对象。这是汇编程序可以解析的尽可能多的机器代码,以及理想情况下用于调试和链接的其他信息。使用反汇编程序,我们可以看到由汇编程序生成的代码:

Disassembly of section .text:

00000000 <fun>:
   0:   e92d4010    push    {r4, lr}
   4:   e3a00005    mov r0, #5
   8:   ebfffffe    bl  0 <more_fun>
   c:   e2800001    add r0, r0, #1
  10:   e8bd8010    pop {r4, pc}

中间的bl 0调用的解析未解决,因为该代码不是原始C源文件的一部分,因此在其中放置了占位符,链接器将在以后出现。 ...这些物体在一起。如果您未指定-c,则gcc还将为您调用链接器。

大多数“工具链”都是以这种方式工作的,这是理智的方式。出于及时和“为什么要爬山,因为那里的原因”的原因,有些编译器更直接地使用机器代码,但是llvm也不这样做,它声称是JIT,尽管其主要用途是JIT。工具链不必使用单独的可执行文件,也无需使用各种方法来解决问题。

我不记得您链接的站点是否应不惜一切代价避免出现在站点列表中,有一个或多个类似的站点包含一些非常糟糕的信息,这些信息令人困惑和错误。该页面既不错也不混乱,但是我只是略读了一下。

反编译器并不真正以人们想编译的形式存在,正如您在此简单示例中看到的那样,原始代码中的信息丢失了,您无法从二进制文件中完全重新创建此代码。制作类似的简单示例来演示这一点很容易。