问题
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"
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
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.
What am I missing here?
回答1:
.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:
.extern is accepted in the source program--for compatibility with other assemblers--but it is ignored.
as
treats all undefined symbols as external.
as
= GNU assembler.
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.
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.
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:
.global makes the symbol visible to ld. If you define symbol in your partial program, its value is made available to other partial programs that are linked with it. Otherwise, symbol takes its attributes from a symbol of the same name from another file linked into the same program.
Both spellings (‘.globl’ and ‘.global’) are accepted, for compatibility with other assemblers.
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.
来源:https://stackoverflow.com/questions/47563403/why-doesnt-the-gcc-assembly-output-generate-a-global-for-printf