深入理解计算机系统——第三章—3.2程序编码

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/weixin_40199047/article/details/102471889

p1.c p2.c \Downarrow
两个文件生成一个可执行文件 \Downarrow
      \implies linux> gcc -Og -o p p1.c p2.c
编译选项 -Og 告诉编译器使用会生成符合原始C代码整体结构的机器代码的优化等级。(太高的优化等级会使代码严重变形,与源代码关系不易理解)

3.2.1 机器级代码

计算机系统使用了多种不同形式的抽象,利用更简单的抽象模型来隐藏实现的细节。对于机器级编程来说,有两种抽象尤为重要。第一种:指令集体系结构或指令集架构(Instruction Set Architecture,ISA)来定义机器级程序格式和行为,它定义了处理器状态指令的格式,以及每条指令对状态的影响。第二种:机器级程序使用的内存地址是虚拟地址,提供的内存模型看上去是一个非常大的字节数组

1) 程序计数器(通常称为“PC”,在 x86-64 中用 %rip 表示)给出将要执行的下一条指令内存中的地址。
2) 整数寄存器文件包含16个命名的位置,分别存储64位的值。
3) 条件码寄存器保存着最近执行的算术或者逻辑指令的状态信息。
4) 一组向量寄存器可以存放一个或多个整数或浮点数值。

程序内存包含:程序的可执行机器代码,操作系统需要的一些信息,用来管理过程调用和返回的运行时栈,以及用户分配的内存块(比如说用 malloc 库函数分配的)。
一条机器指令只执行一个非常基本的操作。

3.2.2 代码示例

#include<stdio.h>

/* mstore.c */

long mult2(long, long);

void multstore(long x, long y, long *dest){
  long t = mult2(x, y);
  *dest = t;
}

生成汇编代码mstore.s. \Downarrow

linux> gcc -Og -S mstore.c
生成目标代码文件mstore.o. \Downarrow
linux> gcc -Og -o mstore.c
反汇编目标代码文件 \Downarrow
linux> objdump -d mstore.o
gcc产生Intel汇编代码 \Downarrow
linux> gcc -Og -S -masm=intel mstore.c

写一个C代码文件 mstore.c , 包含如下的函数定义:

long mult2(long,long);
void multstore(long x,long y,long*dest){
long t = mult2(x,y);
*dest = t;
}

在命令行上使用“-S"选项,就能看到编译器产生的汇编代码,查看 mstroe.s 即可。

Linux> gcc -Og -S mstore.c
Linux> cat ./mstore.s

内容如下:
这里写图片描述
其中有一段代码是这样的:

multstore:
pushq %rbx
movq %rdx, %rbx
call mult2
movq %rax, (%rbx)
popq %rbx
ret

以上从 multstore 之后开始的每一条代码都对应一条机器指令。比如, pushq 表示将寄存器 %rbx 的内容压入栈。
可以使用”-C"选项对其编译并汇编,如:

Linux> gcc -Og -c mstore.c Linux>objdump -d mstore.o

机器代码就是左侧的数字
53 48 89 d3 e8 00 00 00 00 48 89 03 5b c3
右边就是等价的汇编语言。
这里写图片描述
一些机器代码和它的反汇编表示的特性:
1) x86-64 的指令长度从 1 到 15 个字节不等。
2) 设计指令格式的方式是,从某个给定位置开始,可以将字节唯一地解码成机器指令。
3) 反汇编器指数基于机器代码文件中的字节序列来确定汇编代码。它不需要访问该程序的源代码或汇编代码。
4) 反汇编其使用的指令命名规则与GCC生成的汇编代码使用的有些细微的差别。

# include <stdio.h>
void multstore(long , long , long * );
int main(){
long d;
multstore(2 , 3 , &d);
printf("2 * 3 --> %ld/n" , d);
return 0; } long mult2(long a , long b){ long s = a * b ;
return s ; }

同样的方法生成机器代码

Linux>gcc -Og -o prog main.c mstore.c
Linux>objdump -d prog

反汇编器会抽取出各种代码序列,其中包含下面这段:
这里写图片描述
几乎与前面的 mstroe.c 产生的代码一样。

猜你喜欢

转载自blog.csdn.net/weixin_40199047/article/details/102471889