- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在使用 as
和 gcc
来汇编和创建 ARM 汇编程序的可执行文件,正如 this 所推荐的那样教程,如下:
给定一个汇编源文件,program.s
,我运行:
as -o program.o program.s
然后:
gcc -o program program.o
但是,像这样直接在程序集源上运行 gcc
:
gcc -o program program.s
产生相同的结果。
gcc
会在后台调用 as
吗?鉴于 gcc
单独能够从源代码生成可执行文件,是否有任何理由同时使用 as
和 gcc
?
我在 Raspberry Pi 3、Raspbian Jessie(Debian 衍生产品)、gcc 4.9.2 和 2.25 上运行它。
最佳答案
GCC 在幕后调用各种东西;不仅是 as
,还有 ld
。如果您想证明这一点,这很容易检测(将正确的 as
和 ld
以及其他二进制文件替换为打印出命令行的二进制文件,然后运行 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/
我在为 MacOSX 构建的独立包中添加 DMG 背景的自定义图标时遇到问题。我在项目的根目录中添加了一个包。正在从中加载自定义图标,但没有加载 DMG 背景图标。我正在使用 Java fx 2.2.
Qt for Symbian 和 Qt for MeeGo 有什么区别?我知道 Qt 是一个交叉编译平台。这是否意味着如果我使用来自 Qt 的库,完全相同的库可以在所有支持 Qt 的设备(例如 Sym
我正在尝试使用 C# .NET 3.5/4.0 务实地运行 SQL Server 数据库的备份。我已经找到了如何完成此操作,但是我似乎找不到用于备份的命名空间库。 我正在寻找 Microsoft.Sq
我最近在疯狂学习 Java,但我通常是一名 .NET 开发人员。 (所以请原谅我的新手问题。) 在 .Net 中,我可以在不使用 IIS 的情况下开发 ASP.Net 页面,因为它有一个简化的 Web
这post仅当打印命令中有字符串时才有用。现在我有大量的源代码,其中包含一条声明,例如 print milk,butter 应该格式化为 print(milk,butter) 用\n 捕获行尾并不成功
所以我的问题是: https://gist.github.com/panSarin/4a221a0923927115584a 当我保存这个表格时,我收到了标题中的错误 NoMethodError (u
如何让 Html5 音频在点击时播放声音? (ogg 用于 Firefox 等浏览器,mp3 用于 chrome 等浏览器) 到目前为止,我可以通过 onclick 更改为单个文件类型,但我无法像在普
如果it1和it2有什么区别? std::set s; auto it1 = std::inserter(s, s.begin()); auto it2 = std::inserter(s, s.en
4.0.0 com.amkit myapp SpringMVCFirst
我目前使用 Eclipse 作为其他语言的 IDE,而且我习惯于不必离开 IDE 做任何事情 - 但是我真的很难为纯 ECMAScript-262 找到相同或类似的设置。 澄清一下,我不是在寻找 DO
我想将带有字符串数组的C# 结构发送到C++ 函数,该函数接受void * 作为c# 结构和char** 作为c# 结构字符串数组成员。 我能够将结构发送到 c++ 函数,但问题是,无法从 c++ 函
我正在使用动态创建的链接: 我想为f:param附加自定义转换器,以从#{name}等中删除空格。 但是f:param中没有转换器
是否可以利用Redis为.NET创建后写或直写式缓存?理想情况下,透明的高速缓存是由单个进程写入的,并且支持从数据库加载丢失的数据,并每隔一段时间持久保存脏块? 我已经搜查了好几个小时,也许是goog
我正在通过bash执行命令的ssh脚本。 FILENAMES=( "export_production_20200604.tgz" "export_production_log_2020060
我需要一个正则表达式来出现 0 到 7 个字母或 0 到 7 个数字。 例如:匹配:1234、asdbs 不匹配:123456789、absbsafsfsf、asf12 我尝试了([a-zA-Z]{0
我有一个用于会计期间的表格,该表格具有期间结束和开始的开始日期和结束日期。我使用此表来确定何时发生服务交易以及何时在查询中收集收入,例如... SELECT p.PeriodID, p.FiscalY
我很难为只接受字符或数字的 Laravel 构建正则表达式验证。它是这样的: 你好<-好的 123 <- 好的 你好123 <-不行 我现在的正则表达式是这样的:[A-Za-z]|[0-9]。 reg
您实际上会在 Repeater 上使用 OnItemDataBound 做什么? 最佳答案 “此事件为您提供在客户端显示数据项之前访问数据项的最后机会。引发此事件后,数据项将被清空,不再可用。” ~
我有一个 fragment 工作正常的项目,我正在使用 jeremyfeinstein 的 actionbarsherlock 和滑动菜单, 一切正常,但是当我想自定义左侧抽屉列表单元格时,出现异常
最近几天,我似乎平均分配时间在构建我的第一个应用程序和在这里发布问题!! 这是我的第一个应用程序,也是我们的设计师完成的第一个应用程序。我试图满足他所做的事情的外观和感觉,但我认为他没有做适当的事情。
我是一名优秀的程序员,十分优秀!