「C语言」「汇编」C输出hello world!系统发生了什么?
2016-03-05 17:31
573 查看
本篇文章全部摘抄自学长博客供以后学习:
http://efraim.me/2015/12/05/tech-linux-2015-12-05/
排版因与博客园编辑器不同而稍作修改。
输出hello world!系统发生了什么?
经典的hello world!
该段程序,在hello world过程中,系统发生了什么?
0X00 新建hello.c
hello.c文件,是文件由0/1的位(bit)序列,8位组成一组,称为字节,一个个字节表示文件中的一个个字符。
由此引出,系统中的所有信息(磁盘文件,系统程序,网络传输的数据等等),都是一些0/1序列,当我们打开hello.c文件时,系统会按某种规则文件进行解析,最后呈现出人类能看懂的字符,而不是二进制0/1。
区分不同数据对象的唯一方法,就是系统读取这个文件时上下文(可以理解为当时的环境),比如,在不同的上下文中,一个同样的字节序列,有可能表示一个整数,浮点数,字符数或者机器指令。
0x01 解析hello.c
C语言是高级语言,所以这个形式的代码能让人读懂。但系统不认识,为了让系统能认识,需要将hello.c转化成一系机器能认识的语言指令,然后将这些指令按照一种称为可执行目标程序的格式进行打包,并以二进制磁盘文件形式存放,目标程序也可以称为可执行文件。
这里,我用GCC编译器,编译解析hello.c
预处理阶段:-E
预处理器(cpp)主要处理根据以字符#开头的命令,修改原始的C程序。比如hello.c中第一行的#include <stdio.h> 命令会告诉预处理其读区系统头文件stdio.h的内容.并把它直接插入到程序文本中。此过程,会得到以.i作为扩展名。
hello.i文件内容都有些什么呢?
编译阶段:-S
编译器(ccl)将hello.i翻译成文件文件hello.s文件,它包含一个汇编语言程序,汇编程序中的每条语句都以一种标准的文本格式确切地描述了一条条低级机器语言指令.所以该过程会检查代码规范,语法,词法分析,具体如下图.只有编译成功之后,才能生成具体的汇编代码。
汇编阶段:-c
汇编器(as)将hello.s 文件翻译成机器语言指令,,把这些指令打包成一种叫做可重定向目标程序的格式,并且保存在hello.o文件中.该文件是一个二进制文件,他的字节编码是机器语言指令而不是字符,如果用编辑器打开将是一段乱码。
链接阶段:
注意,hello程序调用了printf函数,他是每个C编译器都会提供的标准C库的一个函数.该函数存在于一个名为printf.o的单独的预编译好的文件中,必须将该文件以某种方式合并到我们的hello.o的文件中。连接器(ld),就复制处理这种合并。结果就得到一个hello文件,是一个可执行文件。
http://efraim.me/2015/12/05/tech-linux-2015-12-05/
排版因与博客园编辑器不同而稍作修改。
输出hello world!系统发生了什么?
经典的hello world!
#include <stdio.h> int main () { printf("hello world!"); }
该段程序,在hello world过程中,系统发生了什么?
0X00 新建hello.c
hello.c文件,是文件由0/1的位(bit)序列,8位组成一组,称为字节,一个个字节表示文件中的一个个字符。
由此引出,系统中的所有信息(磁盘文件,系统程序,网络传输的数据等等),都是一些0/1序列,当我们打开hello.c文件时,系统会按某种规则文件进行解析,最后呈现出人类能看懂的字符,而不是二进制0/1。
区分不同数据对象的唯一方法,就是系统读取这个文件时上下文(可以理解为当时的环境),比如,在不同的上下文中,一个同样的字节序列,有可能表示一个整数,浮点数,字符数或者机器指令。
0x01 解析hello.c
C语言是高级语言,所以这个形式的代码能让人读懂。但系统不认识,为了让系统能认识,需要将hello.c转化成一系机器能认识的语言指令,然后将这些指令按照一种称为可执行目标程序的格式进行打包,并以二进制磁盘文件形式存放,目标程序也可以称为可执行文件。
这里,我用GCC编译器,编译解析hello.c
预处理阶段:-E
预处理器(cpp)主要处理根据以字符#开头的命令,修改原始的C程序。比如hello.c中第一行的#include <stdio.h> 命令会告诉预处理其读区系统头文件stdio.h的内容.并把它直接插入到程序文本中。此过程,会得到以.i作为扩展名。
`$ gcc -E hello.c -o hello.i`//预编译hello.c文件 输出hello.i文件
hello.i文件内容都有些什么呢?
//hello.i # 1 "hello.c" # 1 "<built-in>" 1 # 1 "<built-in>" 3 # 325 "<built-in>" 3 # 1 "<command line>" 1 # 1 "<built-in>" 2 # 1 "hello.c" 2 # 1 "/usr/include/stdio.h" 1 3 4 # 64 "/usr/include/stdio.h" 3 4 # 1 "/usr/include/sys/cdefs.h" 1 3 4 # 533 "/usr/include/sys/cdefs.h" 3 4 # 1 "/usr/include/sys/_symbol_aliasing.h" 1 3 4 # 534 "/usr/include/sys/cdefs.h" 2 3 4 # 599 "/usr/include/sys/cdefs.h" 3 4 # 1 "/usr/include/sys/_posix_availability.h" 1 3 4 # 600 "/usr/include/sys/cdefs.h" 2 3 4 # 65 "/usr/include/stdio.h" 2 3 4 # 1 "/usr/include/Availability.h" 1 3 4 # 162 "/usr/include/Availability.h" 3 4 # 1 "/usr/include/AvailabilityInternal.h" 1 3 4 # 163 "/usr/include/Availability.h" 2 3 4 # 66 "/usr/include/stdio.h" 2 3 4 # 1 "/usr/include/_types.h" 1 3 4 # 27 "/usr/include/_types.h" 3 4 # 1 "/usr/include/sys/_types.h" 1 3 4 # 33 "/usr/include/sys/_types.h" 3 4 # 1 "/usr/include/machine/_types.h" 1 3 4 # 32 "/usr/include/machine/_types.h" 3 4 # 1 "/usr/include/i386/_types.h" 1 3 4 # 37 "/usr/include/i386/_types.h" 3 4 typedef signed char __int8_t; typedef unsigned char __uint8_t; typedef short __int16_t; typedef unsigned short __uint16_t; typedef int __int32_t; typedef unsigned int __uint32_t; typedef long long __int64_t; typedef unsigned long long __uint64_t; typedef long __darwin_intptr_t; typedef unsigned int __darwin_natural_t; # 70 "/usr/include/i386/_types.h" 3 4 typedef int __darwin_ct_rune_t;
编译阶段:-S
编译器(ccl)将hello.i翻译成文件文件hello.s文件,它包含一个汇编语言程序,汇编程序中的每条语句都以一种标准的文本格式确切地描述了一条条低级机器语言指令.所以该过程会检查代码规范,语法,词法分析,具体如下图.只有编译成功之后,才能生成具体的汇编代码。
$ gcc -S hello.i -o hello.s
//hello.s .section __TEXT,__text,regular,pure_instructions .macosx_version_min 10, 11 .globl _main .align 4, 0x90 _main: ## @main .cfi_startproc ## BB#0: pushq %rbp Ltmp0: .cfi_def_cfa_offset 16 Ltmp1: .cfi_offset %rbp, -16 movq %rsp, %rbp Ltmp2: .cfi_def_cfa_register %rbp subq $16, %rsp leaq L_.str(%rip), %rdi movl $0, -4(%rbp) movb $0, %al callq _printf xorl %ecx, %ecx movl %eax, -8(%rbp) ## 4-byte Spill movl %ecx, %eax addq $16, %rsp popq %rbp retq .cfi_endproc .section __TEXT,__cstring,cstring_literals L_.str: ## @.str .asciz "hello world!" .subsections_via_symbols
汇编阶段:-c
汇编器(as)将hello.s 文件翻译成机器语言指令,,把这些指令打包成一种叫做可重定向目标程序的格式,并且保存在hello.o文件中.该文件是一个二进制文件,他的字节编码是机器语言指令而不是字符,如果用编辑器打开将是一段乱码。
链接阶段:
注意,hello程序调用了printf函数,他是每个C编译器都会提供的标准C库的一个函数.该函数存在于一个名为printf.o的单独的预编译好的文件中,必须将该文件以某种方式合并到我们的hello.o的文件中。连接器(ld),就复制处理这种合并。结果就得到一个hello文件,是一个可执行文件。
相关文章推荐
- C++字符串学习(一)
- c语言:在3*4的矩阵中,求元素的最大值
- C语言-函数
- 【C++】实现双向链表的所有操作,包括逆置双链表(三种方法)
- 【C++】 双向链表.cpp
- C++ STL <map> 用法简介
- 2016年的C++常见的面试问题详解~搬至牛客网~2
- 一起talk C栗子吧(第二十回:C语言实例--括号匹配)
- 二维数组中的查找
- 橱窗布置c++动态规划
- c++ 学习笔记之动态内存管理
- C++设计模式总结
- C++ string类实现
- c++ 函数的递归调用
- c++ primer plus 第十七章 输入 输出 文件 IO iostream fstream
- c++ 广义表
- Bill学C++ 第三季:求余运算符+运算符结合律
- c\c++中的形参与实参
- C++ 函数的嵌套调用
- c++ const 关键字