X86-64 CPU架构以及64 位GCC对程序编译处理的一些变化
作者:JochenZou
转载请注明出处:http://blog.csdn.net/youkawa/article/details/45458921
- 通用寄存器全部扩展到了64位,寄存器名称前面由R开头,如RAX, RBX, RCX, RDX, RSI和RDI;
- 指令指针(Instruction pointer)、基址指针(base pointer)以及堆栈指针(stack
pointer)也全部扩展到了64位,这些专用寄存器分别称为RIP,RBP,RSP; - 添加了8个通用寄存器R8~R15;
- 指针长度为64位即8-bytes长度;
- 涉及到栈操作的Push/pop指令入栈出栈操作数的长度为64位即8-bytes长度;
- 函数参数主要依靠6个寄存器来传递,当寄存器不够用时才把参数压入栈中存储。按存储参数的顺序(从左到右)依次为RDI, RSI, RDX, RCX, R8, R9;
- 最大canonical address大小为0x00007FFFFFFFFFFF.
- GCC对函数局部变量分配的空间大小为16字节的倍数,例如分配char a[15],则回从[RBP-0X10]地址开始存放局部变量,若定义char a[17],则从[RBP-0X20]地址开始存放局部变量;
- GCC对函数局部变量分配空间有以下几种方式:
(1)当函数内部有调用其他外部函数(有CALL指令)的时候,使用SUB RSP , 0xXX指令分配栈空间, 然后使用MOV [RBP-X], 0xXX的形式入栈,如果没有对局部变量初始化,而且函数后面也没有使用这一变量,则GCC不会为其开辟空间。
(2)当函数内部没有调用其他外部函数时,在进行prologue操作(即push rbp; mov rbp, rsp)之后,不会有SUB RSP , 0xXX指令开辟栈空间的操作,而是直接使用MOV QWORD PTR [RBP-0xXX], 0xXX的方式直接使用栈空间;
(3)当函数内部静态调用lib库函数的时候,因为此时被调用函数内联到了主调函数里面,所以不会有CALL指令,仍然按(2)的方式操作。