对计算机运行逻辑的一些探索

Yuan.Sn

最近学到了数据结构的链式存储结构,加深了对指针和一些存储结构的理解:其实每个数据单位(命令?)在内存中都占有一定的空间,每个单独的数据单位就是通过指针建立联系的,进行各种操作处理。
然后在看代码的时候,突然看到了编程语言最基本的变量赋值操作 int a = 1 。就在想,这个变量a又没有存储其值1的内存地址,那计算机是怎么找到这个1的值呢?

原来是“编译”的功劳

我们写的语言都是高级语言,要在经过高级语言->汇编语言->机器码后才能被CPU理解。

C/C++是通过GCC编译的

像刚才那个简单的代码 int a = 1 我们把它补全为完整的C语言程序:

1
2
3
4
int main{
int a = 1; //就是存1呀!
return 0;
}

在GCC在对这个程序进行编译时,先通过命令 gcc -E file.c -0 file.i 进行对于文件的预处理,在这个过程中,主要就是把头文件展开,删掉注释......
生成的就是后缀为.i的干净C语言程序:

1
2
3
4
5
6
7
8
# 1 "file.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "file.c"
int main(void){
int a = 1;
return 0;
}

之后进行使用 gcc -S file.i -o file.s 进行编译,这个过程主要是把C代码转换为汇编代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
	.file	"file.c"
.text
.def __main; .scl 2; .type 32; .endef
.globl main
.def main; .scl 2; .type 32; .endef
.seh_proc main
main:
pushq %rbp
.seh_pushreg %rbp
movq %rsp, %rbp
.seh_setframe %rbp, 0
subq $48, %rsp
.seh_stackalloc 48
.seh_endprologue
call __main
movl $1, -4(%rbp)
movl $0, %eax
addq $48, %rsp
popq %rbp
ret
.seh_endproc
.ident "GCC: (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 8.1.0"

之后,再进入汇编阶段,使用命令 gcc -c file.s -o file.0 将汇编代码转化为机器指令。这个.o结尾的文件(目标文件),which包含了二进制指令,不能单独执行。因为可能依赖其他文件中的函数或全局变量。
在之后,执行 gcc file.o -o program 链接后就能运行了(win下生成了一个 program.exe)

之后就是CPU的事情了

这个 program.exe 的可执行文件包含了这个C程序的机器码,以及将机器码传给CPU、接收CPU传回的一系列操作,其实就是可以把它当作程序运行在CPU里的“盲盒”,当点击这个“盲盒”时,就会运行你的C程序,并且给你反馈电脑处理后的结果。

Comments