Why doesn't the GCC assembly output generate a .GLOBAL for printf

时光总嘲笑我的痴心妄想 提交于 2020-01-04 04:09:29

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!