64位系统中内存地址为64为,因此含有绝对地址的指令大小比原来增加4个字节.
64位可以表示的数为 264 = 16EB .考虑到实际性能,减少内存管理的开销.实际没用到这么多.
通用寄存器
通用寄存器大小扩展到64位,数量也增加到18个( 新增 R8~R15 寄存器 ).同时,64位本地模式不使用段寄存器:CS , DS , ES , SS , FS , GS. 它们仅用于向下兼容32位.
Call / JMP 指令
此种 Jmp / Call 会直接跳到绝对地址去.
64位中,若此种 Jmp 指令采用绝对地址,则会增加指令长度.因此该指令会被解析为相对地址.
函数调用约定
32位系统采用的函数调用约定包括 cdecl , stdcall , fastcall . 64位系统中把他们统一为一种变形的 fastcall .
这种调用约定最多可以把函数的四个参数存储到寄存器中传递,第五个参数会存入栈来传递.栈中仍然会为前四个参数(32字节)保留空间.
并且传递参数过程中所用的栈由调用者清理.
栈/栈帧
调用子函数时,不再使用 Push 命令,而是使用 Mov 指令来传递参数.并且也不再使用 RBP 寄存器,而是直接使用 RSP 寄存器
优点是,调用子函数时不需要改变栈指针( RSP ),函数返回时也不需要清理栈指针.
64位 Main() 函数:
可以看到,代码起始阶段分配了48h字节大小的栈,并且在 ret 指令之前释放.并且几乎没有使用 Push / Pop 指令.
可以看到,CreateFileA() 的参数是乱序传入的,与 32位 C调用的逆序不同.
前四个使用寄存器,从第五个开始使用栈传递.并且,第五个是从 rsp+20h 开始的,即预留了 32d 字节的空间,可以供函数使用.
在 Win7 x64 系统中,CreateFileA() 里面会调用 CreateFileW() :
在 Win 10 64 位系统中,不存在调用 CreateFileW() 的情况:(原因还不太了解)