37 c assembly naming compilation function
当我看到C应用程序的汇编代码时,如下所示:
emacs hello.c
clang -S -O hello.c -o hello.s
cat hello.s
Run Code Online (Sandbox Code Playgroud)
函数名称以下划线为前缀(例如callq _printf).为什么要这样做,它有什么优势?
例:
你好ç
#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;
}
Run Code Online (Sandbox Code Playgroud)
hello.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:
Run Code Online (Sandbox Code Playgroud)
Jon*_*rdy 29
从连接器和装载器:
在大约1974年用C语言重写UNIX的时候,它的作者已经有了广泛的assember语言库,并且更容易破坏新的C和C兼容代码的名称,而不是返回并修复所有现有代码.现在,20年后,汇编程序代码全部被重写了五次,而UNIX C编译器,特别是那些创建COFF和ELF目标文件的编译器,不再添加下划线.
在C编译的汇编结果中加上下划线只是一个名称错误的约定,它作为一种解决方法而出现.它(据我所知)没有特别的原因,现在已经进入了Clang.
在汇编之外,C标准库通常具有以下划线为前缀的实现定义函数,以传达神奇性的概念,而不是将其触及偶然发现它们的普通程序员.
许多编译器用于将C转换为汇编语言,然后在其上运行汇编程序以生成目标文件.它比直接生成二进制代码容易得多.(AFAIK GCC仍然这样做.但它也有自己的汇编程序.)在此转换过程中,函数名称成为汇编源代码中的标签.但是,如果你有一个叫做(例如)的函数ret,一些汇编程序可能会感到困惑并认为它是一个指令而不是一个标签.(例如,YASM主要是因为标签几乎可以出现在任何地方而且不需要冒号.$如果你想要一个标签,你必须预先添加一个标签ret.)
将字符(例如,下划线)添加到C生成的标签比编写自己的C友好的汇编器或担心标签与汇编指令/指令冲突要容易得多.
如今,汇编程序和编译器已经发生了一些变化,大多数人无论如何都在C级或更高级别工作.因此,在C中破坏名称的最初需求基本消失了.