为什么GCC程序集输出不为printf生成.GLOBAL [英] Why doesn't the GCC assembly output generate a .GLOBAL for printf

查看:154
本文介绍了为什么GCC程序集输出不为printf生成.GLOBAL的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个简单的示例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:

.extern 在源程序中被接受-为了与其他汇编程序兼容-,但被忽略. as 将所有未定义的符号视为外部符号.

.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汇编器.

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:

.global 使符号对ld可见.如果在子程序中定义符号,则其值可用于与其链接的其他子程序.否则,symbol将从链接到同一程序的另一个文件中的同名符号获取其属性.

.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.

为了与其他汇编程序兼容,可以接受两种拼写(".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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆