
概述: 这一章主要是介绍高级语言,例如C语言编写的程序,经过编译后转换为汇编程序。不论我们是在用C语言还是用JAVA或是其他的语言编程时,我们会被屏蔽了程序的机器级的实现。机器语言不需要被编译,可以直接被CPU执行,其执行速度十分快。但是机器语言的读写性与移植性较高级语言低。高级语言被编译后便成为了汇编语言,汇编语言十分接近机器语言。之后汇编代码会转化为机器语言。虽然现代的编译器能帮助我们将高级语言转化为汇编语言,解决了不少问题,但是对于我们正在学习理解计算机系统的学生来说,需要做到能够阅读和理解汇编语言。
Intel处理器系列俗称x86,开始时是第一代单芯片、16位微处理器之一。
每个后继处理器的设计都是后向兼容的——较早版本上编译的代码可以在较新的处理器上运行。
X86 寻址方式经历三代:1、DOS时代的平坦模式,不区分用户空间和内核空间,很不安全。2、8086的分段模式。3、IA32的带保护模式的平坦模式。
ISA:指令集体系结构,机器级程序的指令和格式。它定义了处理状态,指令的格式,以及每条指令对状态的影响。
IA32 指令长度从1到15个字节不等。常用的指令以及操作数较少的指令所需的字节数少,而那些不太常用或者操作数较多的指令所需的字节数较多。
一个C语言程序需要经过四个阶段才能变成一个可执行的二进制代码。
预处理阶段:预处理器cpp根据编译文件以“#”开头的命令,读取系统头文件stdio.h(.h结尾的表示头文件,.c表示可执行文件)的内容,并把它插入到程序文本中,得到一个新的文件。
编译阶段:编译器ccl将预处理后的文件翻译成.s结尾的文本文件,里面包含一个汇编程序。(linux命令:gcc -Og -s hello.c)
汇编阶段:汇编器ss将汇编程序翻译成二进制的机器语言,并把结果保存在以.o结尾的二进制文件中。(linux命令:gcc -Og -c hello.c)
链接阶段:链接器ld将程序用到的C语言类库的函数汇编后的代码合并到hello.o,得到可执行的目标文件。(linux命令:gcc -o hello hello.c)
其中重点:对二进制文件进行反编译:objdump -d hello.o
我对本节内容的问题:gcc产生的汇编代码怎样去查看和阅读。
解答:
先写一个c程序。使用gcc -S编译.c文件,会产生.s文件,打开.s文件即可看到汇编代码。
使用gcc生成目标代码文件,gcc -c .c文件,在当前目录下会产生.o文件的二进制代码,如果要打开这个文件,可以使用反汇编器,objdump -d .o文件,即可查看。
GCC产生的汇编代码有点难读,它包含一些我们不关心的信息。所有以 "." 开头的行都是指导汇编器和链接器的命令,称为“汇编器命令”。
Inter使用术语“字(word)”表示16位数据类型,因此32位数为“双字”,64位数为“四字”。
大多数GCC生成的汇编代码指令都有一个字符的后缀,表明操作数的大小。例如数据传送指令有五个变种:movb=传送字节、movw=传送字、movl=传送双子、movq=传送四字、movbsq=传送绝对的四字。
最初的8086中有8个16位的寄存器,即上图的%ax到%bp。扩展到IA32架构时,这些寄存器也扩展到32为位寄存器,标号从%eax到%ebp。扩展到x86-64后,原来的8位寄存器扩展到64位,标号从%rax到%rbp。除此之外还增加了8个新的寄存器,命名为%r8到%r15。
在再常见的程序里不同的寄存器扮演着不同的角色。其中最重要的是栈指针%rsp,用来指明运行时栈的结束位置。
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/tongxinshuyu/article-54154-1.html
必须给他弄沉
在此期限内有足够高的可靠性