问题描述
我有一个简单的示例C程序:-
I have a trivial example C program:-
#include <stdio.h>
int main()
{
printf("hello world!");
return 1;
}
我使用以下命令对其进行编译并生成程序集:-
I use the following command to compile it and generate assembly:-
riscv32-unknown-elf-gcc -S hello.c -o hello.asm
哪个生成以下程序集:-
Which generates the following assembly: -
.file "hello.c"
.option nopic
.section .rodata
.align 2
.LC0:
.string "hello world!"
.text
.align 2
.globl main
.type main, @function
main:
addi sp,sp,-16
sw ra,12(sp)
sw s0,8(sp)
addi s0,sp,16
lui a5,%hi(.LC0)
addi a0,a5,%lo(.LC0)
call printf
li a5,1
mv a0,a5
lw ra,12(sp)
lw s0,8(sp)
addi sp,sp,16
jr ra
.size main, .-main
.ident "GCC: (GNU) 7.2.0"
有一个预期的call printf
行,但是因为在此汇编文件中没有printf的实现,所以我希望看到它请求具有此类内容的外部实现...
There is an expected call printf
line but because there is no implementation of the printf inside this assembly file I would have expected to see it request an external implementation with something like this...
.global printf
但是程序集中没有这样的行.我认为,如果没有全局指令,则意味着链接器将仅尝试将其解析为该单个程序集文件中的标签.我认为这是global指令的重点,因此,除非使用.global导出以从其他对象文件访问,或者也通过使用.global从另一个对象文件导入,否则所有标签都在单个程序集文件中是本地的.
But there is no such line in the assembly. I thought that without the global directive it meant that the linker will only try and resolve it to labels inside this single assembly file. I thought that was the whole point of the global directive, so that all the labels are local to the single assembly file unless exported using .global for access from other object files or import from another object file by also using .global.
我在这里想念什么?
推荐答案
.global
会将当前文件中的标签标记为具有全局范围(可用于其他模块).也许您是说.extern
.尽管可以使用.extern
表示标签是外部标签,但GNU汇编程序实际上忽略了该指令.从手册:
.global
would mark a label in the current file as having global scope (available to other modules). Maybe you meant .extern
. Although .extern
can be used to say a label is external, the directive is actually ignored by GNU Assembler. From the manual:
as
= GNU汇编器.
as
= GNU assembler.
GNU汇编程序假定当前文件中不知道的任何标签都是外部引用.由链接器确定是否未定义.这就是为什么您看不到任何将printf
标记为外部的指令的原因.在GNU汇编程序中,这是没有必要的.
GNU assembler assumes that any label it doesn't know about in the current file is an external reference. It is up to the linker to determine if it is undefined or not. That is why you don't see any directive marking printf
as being external. In GNU assembler it just isn't necessary.
注意:造成混淆的部分原因可能是像NASM/YASM这样的汇编器需要显式的extern
语句来表示符号不在被汇编的本地模块中.这些汇编器将返回错误,即未定义符号.这是GNU汇编程序和NASM/YASM之间的区别.
Note: Part of the confusion may be in that assemblers like NASM/YASM require an explicit extern
statement to denote that a symbol is not within the local module being assembled. Those assemblers will return with an error that a symbol was undefined. This is one difference between GNU Assembler and NASM/YASM.
.global
.directive不会导入标签,因为它实际上是导出的.它仅将当前文件中的标签标记为对其他模块全局可用.它不用于从其他模块导入标签.从手册中:
The .global
.directive doesn't import labels, as it is essentially export. It only marks labels in the current file as globally available to other modules. It is not used for importing labels from other modules. From the manual:
为了与其他汇编程序兼容,可以接受两种拼写(".globl"和".global").
Both spellings (‘.globl’ and ‘.global’) are accepted, for compatibility with other assemblers.
有一个.global main
指令将main
标记为全局.没有它,链接器将假定main
本质上是特定于模块的静态标签,其他模块无法使用. C 运行时库需要访问main
,因为必须将main
作为将控制权转移到 C 代码条目的最后一步.
There is a .global main
directive to mark main
as global. Without it the linker will assume that main
is essentially a static label specific to a module and not usable by other modules. The C runtime library needs access to main
since main
must be called as the last step of transferring control to the entry of your C code.
这篇关于为什么GCC程序集输出不为printf生成.GLOBAL的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!