¿Cuál es la razón por la cual los nombres de las funciones tienen como prefijo un subrayado del compilador?
function assembly (3)
A primera vista, el sistema operativo se ejecuta en Unix / Unix en una PC. Según mi opinión, no hay nada sorprendente que encuentre _printf en el lenguaje ensamblador generado. C printf es una función que realiza una E / S. Por lo tanto, es responsabilidad del kernel + driver realizar la E / S solicitada.
La ruta de las instrucciones de la máquina tomada en cualquier sistema operativo tipo Unix / Unix es la siguiente:
printf (código C) -> _printf (libc) -> trap -> kernel + driver work -> return from trap -> return desde _printf (libc) -> printf completion y return -> next machine instruction en código C
En el caso de este extracto de código de ensamblaje, parece que C printf está en línea por el compilador lo que hizo que el punto de entrada _printf sea visible en el código de ensamblaje.
Para asegurarse de que C printf no se decore con un prefijo (un guion bajo en este caso), lo mejor es buscar en todos los encabezados C un _printf con un comando como:
find / usr / include -name * .h -exec grep _printf {} /; -impresión
Cuando veo el código ensamblador de una aplicación C, así:
emacs hello.c
clang -S -O hello.c -o hello.s
cat hello.s
Los nombres de las funciones tienen como prefijo un subrayado (por ejemplo, callq _printf
). ¿Por qué se hace esto y qué ventajas tiene?
Ejemplo:
Hola C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
char *myString = malloc(strlen("Hello, World!") + 1);
memcpy(myString, "Hello, World!", strlen("Hello, World!") + 1);
printf("%s", myString);
return 0;
}
hola.s
_main: ; Here
Leh_func_begin0:
pushq %rbp
Ltmp0:
movq %rsp, %rbp
Ltmp1:
movl $14, %edi
callq _malloc ; Here
movabsq $6278066737626506568, %rcx
movq %rcx, (%rax)
movw $33, 12(%rax)
movl $1684828783, 8(%rax)
leaq L_.str1(%rip), %rdi
movq %rax, %rsi
xorb %al, %al
callq _printf ; Here
xorl %eax, %eax
popq %rbp
ret
Leh_func_end0:
En el momento en que UNIX se reescribió en C en 1974, sus autores ya tenían extensas bibliotecas de idiomas assember, y era más fácil manipular los nombres de los nuevos códigos compatibles con C y C que retroceder y corregir todo el código existente. Ahora, 20 años después, el código ensamblador se ha reescrito cinco veces, y los compiladores C de UNIX, particularmente los que crean archivos de objeto COFF y ELF, ya no preceden al guión bajo.
El anteponer un guión bajo en los resultados del ensamblaje de la compilación C es solo una convención de manipulación de nombres que surgió como una solución alternativa. Se mantuvo alrededor (hasta donde sé) ninguna razón en particular, y ahora ha llegado a Clang.
Fuera del ensamblaje, la biblioteca estándar de C a menudo tiene funciones definidas por la implementación con un guión bajo para transmitir nociones de magia y no tocar esto con los programadores ordinarios que tropiezan con ellos.
Muchos compiladores solían traducir C al lenguaje ensamblador y luego ejecutaban un ensamblador para generar un archivo objeto. Es mucho más fácil que generar código binario directamente. (AFAIK GCC todavía lo hace, pero también tiene su propio ensamblador). Durante esta traducción, los nombres de las funciones se convierten en etiquetas en el origen del ensamblaje. Sin embargo, si tiene una función llamada (por ejemplo) ret
, algunos ensambladores pueden confundirse y pensar que es una instrucción en lugar de una etiqueta. (YASM lo hace, por ejemplo, principalmente porque las etiquetas pueden aparecer prácticamente en cualquier lugar y no requieren dos puntos. Tiene que anteponer un $
si desea una etiqueta llamada ret
).
Agregar un carácter (como, por ejemplo, un guión bajo) a las etiquetas generadas en C fue mucho más fácil que escribir el propio ensamblador C o preocuparse por las etiquetas que chocan con las instrucciones / instrucciones de ensamblaje.
En la actualidad, los ensambladores y los compiladores han evolucionado un poco, y la mayoría de las personas trabajan en el nivel C o superior de todos modos. Entonces, la necesidad original de modificar los nombres en C ya no existe.