kahou

导航

汇编小记-1

先来一小段汇编的翻译:

movl    %edi, -4(%rbp)          *(unsigned*)(rbp - 4) = edi;

movl    -4(%rbp), %eax          eax = *(unsigned*)(rbp - 4);

addl    $8, %eax             eax = eax + 8;             
其实刚开始,是对这个-4有疑问的,不知道汇编里还有这个用法,后来才知道,是一个寄存器的寻址操作来的,括号外面允许提供一个偏移量,即访问指针指向内存,可加适当的偏移量,无需改变指针值,避免了指针值的计算,这样会有一些效率的提升,这是 CPU 硬件支持的,偏移量会成为指令编码的字段之一。

在比如说 unsigned *ptr = A; 然后你会频繁访问 A+0, A+4, A+8, A+16, 然后你可以把 A 装入 rbp,这几个访问就可以表示为 0(%rbp),  4(%rbp),  8(%rbp),  16(%rbp),不必来回加减 rbp。如果没有偏移这个特性,rbp 是每次都要变的,多一条指令就多了几个时钟周期,慢了几个纳秒。做同样的事情,当然越快越好,指令数目少也是快的一种途径。

我们用指针访问某个元素的时候,比如 ptr += 8; *ptr,  就不小心多出 ptr += 8; 这个操作,如果是下标访问,那就是 ptr[8],编译器会尽量将下标访问翻译为偏移表达式的形式,所以少了 ptr += 8; ,就更快了。

很多情况下我们抠的是健壮性,可读性,稳定性,所以那些也就无所谓了,这大多是控制类软件的情况,但是如果是性能类的软件,还真的抠那么几个纳秒呢。

ptr += 8,  假设 ptr 为 char* 类型,装入 eax, 则会多出 addl $8, %eax 这一条指令。编译器的任务就是把 C 语言翻译为汇编语言,利用适当的 CPU 寄存器,适当的汇编指令,实现对应的运算处理。
加减,移位,与,或,非,异或,比较,搬移(move)都是基本的运算。
指令可以分类:算数运算指令(+,-,*,/),逻辑运算指令(与,或,非,异或),移位运算指令(左移,右移),分支控制指令(跳转指令),比较指令,搬移指令这些基本的运算,组合成了功能强大的计算机操作系统。
CPU 内部,无非是数据搬来搬去,算来算去,比来比去,跳来跳去(根据比对结果 大于,小于,等于 等,进行条件跳转)
栈这个东西也是 CPU 的一个特性操作
CPU 会有一个堆栈指针寄存器,进行典型的 push,pop 操作
这个东西也是函数调用很关键的一个东西,关系到参数传递和函数返回

posted on 2018-07-11 10:28  kahou  阅读(227)  评论(0编辑  收藏  举报