程序的机器级表示 - 程序的编码

用户头像
引花眠
关注
发布于: 2020 年 07 月 12 日

计算机执行的代码

我们一般使用高级语言编程,比如C、Java等,使用这些语言的时候,我们实际是不知道计算机底层的一些细节,操作系统与高级语言本身,将很多细节屏蔽了;高级语言是对人友好的,它其实只是方便我们人来阅读,而对于计算机其是不能识别高级语言的。

计算机实际执行的是机器代码,用字节序列编码低级的操作,包括处理数据、管理内存、读写存储设备上的数据,以及网络通讯。–《深入理解计算机系统-原书第三版-第三章程序的机器级表示》

机器语言(机器代码)是与特定的计算机相关的,不同系列的计算机其机器语言是互不相同的,机器语言其实就是特定的二进制序列,虽然其能够直接被计算机识别,但是机器语言写的程序存在不便于阅读、难以记忆的问题,也就是对于人不够友好。

为了解决这个问题,人们使用助记符号代替机器语言中的指令,这就形成了汇编语言。汇编语言使指令容易理解和记忆,而且便于交流,使计算机软件的发展大大前进了一步。但是,由于计算机只认识机器语言,所以用汇编语言编写的程序还必须翻译成机器指令码,计算机才能识别和执行。这种翻译工作也可由计算机来完成,具有这种翻译功能的程序就是汇编程序。

程序的编码

虽然有了汇编语言,但是使用其编程耗费的时间还是太大,所以人们为了更容易编程,发明了各种高级语言,如C、FORTRAN、Lisp等语言。高级语言比机器语言、汇编语言更接近人的语言,用户可以不必了解计算机的指令系统和具体结构,就能够编制程序,大大提高了编程的效率,而且高级语言的可移植性比汇编语言强很多。

但是要执行用高级语言编写的程序,需要将其转化为机器可执行的代码,这个过程就是编译,将一种格式的编码转换为另一种格式的编码。

C语言与汇编语言

对于如下C语言代码:

#include <stdio.h>
int add(int, int);
int main(){
int ans = add(5,6);
printf("5+6=%d\n",ans);
}
int add(int a, int b){
return a + b;
}

我们可以用命令查看其编译为汇编语言后的代码,gcc -S add.c

.file "add.c"
.text
.section .rodata
.LC0:
.string "5+6=%d\n"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $16, %rsp
movl $6, %esi
movl $5, %edi
call add
movl %eax, -4(%rbp)
movl -4(%rbp), %eax
movl %eax, %esi
leaq .LC0(%rip), %rdi
movl $0, %eax
call printf@PLT
movl $0, %eax
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.globl add
.type add, @function
add:
.LFB1:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl %edi, -4(%rbp)
movl %esi, -8(%rbp)
movl -4(%rbp), %edx
movl -8(%rbp), %eax
addl %edx, %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE1:
.size add, .-add
.ident "GCC: (GNU) 10.1.0"
.section .note.GNU-stack,"",@progbits



对于add函数,c语言对应的汇编代码去除标记之后有:

pushq %rbp
movq %rsp, %rbp
movl %edi, -4(%rbp)
movl %esi, -8(%rbp)
movl -4(%rbp), %edx
movl -8(%rbp), %eax
addl %edx, %eax
popq %rbp
ret


将其编译为二进制代码后,objdump -d add.out,add相关的反编译后的汇编代码如下:

0000000000001170 <add>:
1170: 55 push %rbp
1171: 48 89 e5 mov %rsp,%rbp
1174: 89 7d fc mov %edi,-0x4(%rbp)
1177: 89 75 f8 mov %esi,-0x8(%rbp)
117a: 8b 55 fc mov -0x4(%rbp),%edx
117d: 8b 45 f8 mov -0x8(%rbp),%eax
1180: 01 d0 add %edx,%eax
1182: 5d pop %rbp
1183: c3 retq
...


其与编译器直接输出的汇编代码大致相同。

C语言与汇编语言的区别

  1. 汇编语言能够操作一些底层的硬件,比如指令寄存器%rip,某些整数寄存器,条件码寄存,向量寄存器等,而这些对于C语言是不可见的。

  2. C语言有各种数据类型,但是对于汇编语言来说,都是字节序列,它只是将内存看作一个大的字节序列数组。

参考资料

  1. 百度百科-机器语言

  2. 百度百科-汇编语言

  3. 豆瓣-深入理解计算机系统(原书第3版)



发布于: 2020 年 07 月 12 日 阅读数: 65
用户头像

引花眠

关注

还未添加个人签名 2018.06.11 加入

还未添加个人简介

评论

发布
暂无评论
程序的机器级表示-程序的编码