У меня есть тривиальный пример программы C: -
#include <stdio.h>
int main()
{
printf("hello world!");
return 1;
}
Я использую следующую команду для компиляции и создания сборки:
riscv32-unknown-elf-gcc -S hello.c -o hello.asm
Что генерирует следующую сборку: -
.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, я ожидал увидеть, что он запрашивает внешнюю реализацию с чем-то вроде этого...
.global printf
Но такой строчки в сборке нет. Я думал, что без глобальной директивы это означало, что компоновщик будет пытаться преобразовать ее только в метки внутри этого единственного файла сборки. Я думал, что в этом весь смысл глобальной директивы, так что все метки являются локальными для одного файла сборки, если только они не экспортируются с использованием .global для доступа из других объектных файлов или не импортируются из другого объектного файла с использованием также .global.
Что мне здесь не хватает?
.global
пометит метку в текущем файле как имеющую глобальную область действия (доступную для других модулей). Возможно, вы имели в виду.extern
. Хотя с помощью.extern
можно указать, что метка является внешней, эта директива фактически игнорируется. Ассемблер GNU предполагает, что любая метка, о которой он не знает в текущем файле, автоматически считается внешней (определить, является ли она неопределенной, зависит от компоновщика). Вот почему вы не видите никакой директивы, помечающейprintf
как внешнюю — в этом нет необходимости. - person Michael Petch   schedule 30.11.2017