gpt4 book ai didi

gcc - as + gcc vs gcc 仅用于 ARM 汇编

转载 作者:行者123 更新时间:2023-12-05 01:01:09 28 4
gpt4 key购买 nike

我正在使用 asgcc 来汇编和创建 ARM 汇编程序的可执行文件,正如 this 所推荐的那样教程,如下:

给定一个汇编源文件,program.s,我运行:

as -o program.o program.s

然后:

gcc -o program program.o

但是,像这样直接在程序集源上运行 gcc:

gcc -o program program.s

产生相同的结果。

gcc 会在后台调用 as 吗?鉴于 gcc 单独能够从源代码生成可执行文件,是否有任何理由同时使用 asgcc

我在 Raspberry Pi 3、Raspbian Jessie(Debian 衍生产品)、gcc 4.9.2 和 2.25 上运行它。

最佳答案

GCC 在幕后调用各种东西;不仅是 as,还有 ld。如果您想证明这一点,这很容易检测(将正确的 asld 以及其他二进制文件替换为打印出命令行的二进制文件,然后运行 ​​GCC 并看到二进制文件被调用)。

当你使用 GCC 作为汇编器时,它会经过一个 C 预处理器,所以你可以做一些相当恶心的事情,比如:

开始.s

//this is a comment
@this is a comment
#define FOO BAR

.globl _start
_start:
mov sp,#0x80000
bl hello
b .

.globl world
world:
bx lr

要查看更多内容,请查看其他文件:

所以.h

unsigned int world ( unsigned int, unsigned int );

#define FIVE 5
#define SIX 6

so.c

#include "so.h"

unsigned int hello ( void )
{
unsigned int a,b,c;
a=FIVE;
b=SIX;
c=world(a,b);
return(c+1);
}

构建

arm-none-eabi-gcc -save-temps -nostdlib -nostartfiles -ffreestanding -O2 start.s so.c -o so.elf
arm-none-eabi-objdump -D so.elf

生产

00008000 <_start>:
8000: e3a0d702 mov sp, #524288 ; 0x80000
8004: eb000001 bl 8010 <hello>
8008: eafffffe b 8008 <_start+0x8>

0000800c <world>:
800c: e12fff1e bx lr

00008010 <hello>:
8010: e92d4010 push {r4, lr}
8014: e3a01006 mov r1, #6
8018: e3a00005 mov r0, #5
801c: ebfffffa bl 800c <world>
8020: e8bd4010 pop {r4, lr}
8024: e2800001 add r0, r0, #1
8028: e12fff1e bx lr

是一个非常简单的项目。这是预处理器之后的 so.i,它会获取包含文件并替换定义:

# 1 "so.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "so.c"


# 1 "so.h" 1

unsigned int world ( unsigned int, unsigned int );
# 4 "so.c" 2

unsigned int hello ( void )
{
unsigned int a,b,c;
a=5;
b=6;
c=world(a,b);
return(c+1);
}

然后 GCC 调用实际的编译器(其程序名称不是 GCC)。

产生so.s:

    .cpu arm7tdmi
.eabi_attribute 20, 1
.eabi_attribute 21, 1
.eabi_attribute 23, 3
.eabi_attribute 24, 1
.eabi_attribute 25, 1
.eabi_attribute 26, 1
.eabi_attribute 30, 2
.eabi_attribute 34, 0
.eabi_attribute 18, 4
.file "so.c"
.text
.align 2
.global hello
.syntax unified
.arm
.fpu softvfp
.type hello, %function
hello:
@ Function supports interworking.
@ args = 0, pretend = 0, frame = 0
@ frame_needed = 0, uses_anonymous_args = 0
push {r4, lr}
mov r1, #6
mov r0, #5
bl world
pop {r4, lr}
add r0, r0, #1
bx lr
.size hello, .-hello
.ident "GCC: (GNU) 6.3.0"

然后将其馈送到汇编器以制作 so.o。然后调用链接器将这些变成so.elf。

现在,您可以直接进行大部分通话。这并不意味着这些程序有它们调用的其他程序。 GCC 仍然调用一个或多个程序来实际进行编译。

arm-none-eabi-as start.s -o start.o
arm-none-eabi-gcc -O2 -S so.c
arm-none-eabi-as so.s -o so.o
arm-none-eabi-ld start.o so.o -o so.elf
arm-none-eabi-objdump -D so.elf

给出相同的结果:

00008000 <_start>:
8000: e3a0d702 mov sp, #524288 ; 0x80000
8004: eb000001 bl 8010 <hello>
8008: eafffffe b 8008 <_start+0x8>

0000800c <world>:
800c: e12fff1e bx lr

00008010 <hello>:
8010: e92d4010 push {r4, lr}
8014: e3a01006 mov r1, #6
8018: e3a00005 mov r0, #5
801c: ebfffffa bl 800c <world>
8020: e8bd4010 pop {r4, lr}
8024: e2800001 add r0, r0, #1
8028: e12fff1e bx lr

在 GCC 中使用 -S 确实感觉有点不对劲。像这样使用它反而感觉更自然:

arm-none-eabi-gcc -O2 -c so.c -o so.o

现在有一个链接器脚本,我们没有提供工具链默认的链接器脚本。我们可以控制它,并且根据它的目标,也许我们应该控制它。

我很不高兴看到 as 的新/当前版本能够容忍 C 注释等...以前不是这样的,必须是新的东西最新版本。

因此,术语“工具链”是一系列链接在一​​起的工具,一个按顺序链接到下一个。

并非所有编译器都采用汇编语言步骤。有些编译成中间代码,然后还有另一个工具可以将编译器特定的中间代码转换为汇编语言。然后调用一些汇编程序(GCC 的中间代码在编译步骤中的表内,您可以在 clang/llvm 中要求它编译为此代码,然后从那里转到其中一个目标的汇编语言)。

一些编译器直接使用机器代码而不是汇编语言。这可能是那些“仅仅因为它在那里就爬山”与“四处走动”的事情之一。就像纯粹用汇编语言编写操作系统一样。

对于任何大小合适的项目和可以支持它的工具,您将拥有一个链接器和一个汇编器,这是您为支持新目标而制作的第一个工具。处理器(芯片或 ip 或两者)供应商将拥有一个汇编程序,然后还有其他可用的工具。

尝试使用汇编语言手动编译上述简单的 C 程序。然后再次尝试使用汇编语言,手动,只使用机器代码。您会发现,使用汇编语言作为中间步骤对于编译器开发人员来说要明智得多,而且它一直都是这样做的,这也是继续这样做的一个很好的理由。

如果你在你正在使用的 gnu 工具链目录中闲逛,你可能会发现类似 cc1 的程序:

./libexec/gcc/arm-none-eabi/6.3.0/cc1 --help
The following options are specific to just the language Ada:
None found. Use --help=Ada to show *all* the options supported by the Ada front-end.

The following options are specific to just the language AdaSCIL:
None found. Use --help=AdaSCIL to show *all* the options supported by the AdaSCIL front-end.

The following options are specific to just the language AdaWhy:
None found. Use --help=AdaWhy to show *all* the options supported by the AdaWhy front-end.

The following options are specific to just the language C:
None found. Use --help=C to show *all* the options supported by the C front-end.

The following options are specific to just the language C++:
-Wplacement-new
-Wplacement-new= 0xffffffff

The following options are specific to just the language Fortran:

现在,如果您针对使用 -save-temps 保存的 so.i 文件运行 cc1 程序,您将获得 so.s 汇编语言文件。

您可能会继续挖掘目录或 gnu 工具源以找到更多好东西。

请注意,这个问题之前已经在 Stack Overflow 上以各种方式问过很多次了。

还请注意,main() 并没有什么特别之处,正如我所展示的那样。在某些编译器中可能是这样,但我可以制作不需要该函数名的程序。

关于gcc - as + gcc vs gcc 仅用于 ARM 汇编,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45527732/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com