背景
64位还有很长的时间发展,甚至目前存储只需要48位就行了。
机器字长的发展
8位机 6502
超级玛丽,只需要kb级别的内存就能跑。
16bit PC寄存器,64BiB寻址能力,没有乘除法、浮点数
16位机 8086/8088
- 8086:16位寄存器
- 8088:20位寄存器(MB级别内存),计算机从军用迈向民用的序幕
- 能打印,有文本处理能力,没有GUI
32位机 intel x86
- 4GB内存
- 基本满足现实需求,比如说游戏

64位机
- x86-64、AArch64、RV64
- iPhone 5S:第一款64位手机
从int看计算机发展
int类型的长度:
- 8 bit computer: 8bit
- 16 bit computer: 16 bit
- 32 bit computer: 32 bit
- 64 bit computer: 32 bit
- JVM(32/64 bit): 32 bit
在逻辑世界里描述日常世界,2,147,483,647 已经足够大了
ABI
see: ABI
cdecl函数调用
- caller stack frame
- 所有参数以数组形式保存在堆栈上(反序压栈)
- 返回地址
- 跳转到callee
- callee
- EAX作为返回值
- 其他寄存器都是callee save
void bar(int*);
int foo(int x){
bar(&x);
return x;
}x86-64体系结构与汇编语言
寄存器
- 部分继承自IA32:
- 部分用来默认传参:
- 不用堆栈传参了

- 更难读懂汇编代码了o(TヘTo)
A+B in x86-64
int f(int a, int b){return a+b;}
- rdi、rsi:默认传参寄存器,分别对应第一个第二个参数
- lea:相对1倍的偏移寻址
max in x86-64
if(a>b)return a;
else return b;
- cmovge:大于或等于时赋值
很多参数的例子
支持6个参数的传递,可大幅减少堆栈内存的访问
void plus(int a, int b){
fprintf(stdout, "%d + %d = %d\n", a, b, a+b);
}- 实际调用的是_fprintf_.chk@plt
- 需要传递的参数:stdout,%d+%d=%d小n,a,b,a+b
- calling convention:rdi,rsi,rdx,rcx,r8,r9


对比32位printf汇编,看样子更简洁,更快

取地址
如果我对寄存器上的参数取地址咋办?
编译器会将有取地址操作的变量放到栈上

Inline Assembly
在c代码中插入汇编代码:
int foo(int x, int y){
asm("endbr64;"
".byte 0xf3, 0x0f, 0x1e, 0xfa");
return x;
}int foo(int x, int y){
int z;
asm("addl %a, %2;"
"movl %2, %0"
: "=&r"(z) //output,强制用不同的寄存器
: "r"(x), "r"(y) //input
);
return x;
}