页面加载中,请稍候
来源:开源Linux发布时间:2023-04-26585浏览
询问 AI
链接:https://blog.csdn.net/qq_39221436/article/details/125638972
大家肯定都知道计算机程序设计语言通常分为机器语言、汇编语言和高级语言三类。高级语言需要通过翻译成机器语言才能执行,而翻译的方式分为两种,一种是编译型,另一种是解释型,因此我们基本上将高级语言分为两大类,一种是编译型语言,例如C,C++,Java,另一种是解释型语言,例如Python、Ruby、MATLAB 、JavaScript。本文将介绍如何将高层的C/C++语言编写的程序转换成为处理器能够执行的二进制代码的过程,包括四个步骤:
#include<stdio.h>
//此程序很简单,仅仅打印一个Hello World的字符串。
intmain(void)
{
printf("HelloWorld!\n");
return0;
}
$gcc-Ehello.c-ohello.i//将源文件hello.c文件预处理生成hello.i
//GCC的选项-E使GCC在进行完预处理后即停止
hello.i文件可以作为普通文本文件打开进行查看,其代码片段如下所示:// hello.i代码片段
externvoidfunlockfile(FILE*__stream)__attribute__((__nothrow__,__leaf__));
#942"/usr/include/stdio.h"34
#2"hello.c"2
#3"hello.c"
int
main(void)
{
printf("HelloWorld!""\n");
return0;
}
$gcc-Shello.i-ohello.s//将预处理生成的hello.i文件编译生成汇编程序hello.s
//GCC的选项-S使GCC在执行完编译后停止,生成汇编程序
上述命令生成的汇编程序hello.s的代码片段如下所示,其全部为汇编代码。//hello.s代码片段
main:
.LFB0:
.cfi_startproc
pushq%rbp
.cfi_def_cfa_offset16
.cfi_offset6,-16
movq%rsp,%rbp
.cfi_def_cfa_register6
movl$.LC0,%edi
callputs
movl$0,%eax
popq%rbp
.cfi_def_cfa7,8
ret
.cfi_endproc
$gcc-chello.s-ohello.o//将编译生成的hello.s文件汇编生成目标文件hello.o
//GCC的选项-c使GCC在执行完汇编后停止,生成目标文件
//或者直接调用as进行汇编
$as-chello.s-ohello.o//使用Binutils中的as将hello.s文件汇编生成目标文件
注意:hello.o目标文件为ELF(Executable and Linkable Format)格式的可重定向文件。$gcchello.c-ohello
$sizehello//使用size查看大小
textdatabssdechexfilename
1183552817436cfhello
$lddhello//可以看出该可执行文件链接了很多其他动态库,主要是Linux的glibc动态库
linux-vdso.so.1=>(0x00007fffefd7c000)
libc.so.6=>/lib/x86_64-linux-gnu/libc.so.6(0x00007fadcdd82000)
/lib64/ld-linux-x86-64.so.2(0x00007fadce14c000)
如果使用命令“gcc -static hello.c -o hello”则会使用静态库进行链接,生成的ELF可执行文件的大小(使用Binutils的size命令查看)和链接的动态库(使用Binutils的ldd命令查看)如下所示:$gcc-statichello.c-ohello
$sizehello//使用size查看大小
textdatabssdechexfilename
82372672846360837370cc6fahello//可以看出text的代码尺寸变得极大
$lddhello
notadynamicexecutable//说明没有链接动态库
链接器链接后生成的最终文件为ELF格式可执行文件,一个ELF可执行文件通常被链接为不同的段,常见的段譬如.text、.data、.rodata、.bss等段。
可以使用readelf -S查看其各个section的信息如下:$readelf-Shello
Thereare31sectionheaders,startingatoffset0x19d8:
SectionHeaders:
[Nr]NameTypeAddressOffset
SizeEntSizeFlagsLinkInfoAlign
[0]NULL000000000000000000000000
00000000000000000000000000000000000
……
[11].initPROGBITS00000000004003c8000003c8
000000000000001a0000000000000000AX004
……
[14].textPROGBITS000000000040043000000430
00000000000001820000000000000000AX0016
[15].finiPROGBITS00000000004005b4000005b4
……
$objdump-Dhello
……
0000000000400526<main>://main标签的PC地址
//PC地址:指令编码指令的汇编格式
400526:55push%rbp
400527:4889e5mov%rsp,%rbp
40052a:bfc4054000mov$0x4005c4,%edi
40052f:e8ccfeffffcallq400400<puts@plt>
400534:b800000000mov$0x0,%eax
400539:5dpop%rbp
40053a:c3retq
40053b:0f1f440000nopl0x0(%rax,%rax,1)
……
使用objdump -S将其反汇编并且将其C语言源代码混合显示出来:$gcc-ohello-ghello.c//要加上-g选项
$objdump-Shello
……
0000000000400526<main>:
#include<stdio.h>
int
main(void)
{
400526:55push%rbp
400527:4889e5mov%rsp,%rbp
printf("HelloWorld!""\n");
40052a:bfc4054000mov$0x4005c4,%edi
40052f:e8ccfeffffcallq400400<puts@plt>
return0;
400534:b800000000mov$0x0,%eax
}
400539:5dpop%rbp
40053a:c3retq
40053b:0f1f440000nopl0x0(%rax,%rax,1)
……
10T 技术资源大放送!包括但不限于:Linux、虚拟化、容器、云计算、网络、Python、Go 等。在开源Linux公众号内回复10T,即可免费获取!
新闻来源:开源Linux,文中所述为作者独立观点,不代表icspec立场。更多精彩资讯请下载icspec App。如对本稿件有异议,请联系微信客服specltkj。
暂无评论哦,快来评论一下吧!
2 天前

2026-06-04
2026-07-22