X86 X64 arm64
arm64 精简指令集
X86 复杂指令集 32位
X64 复杂指令集 64位
寄存器
向下兼容
应用程序地址空间
操作系统通过虚拟内存的方式为所有应用程序提供了统一的内存映射地址。如图3所示,从上到下分别是用户栈、共享库内存、运行时堆和代码段。当然这个是一个大概的分段,实际分段比这个可能稍微复杂一些,但整个格局没有大变化。
函数调用及汇编指令
函数调用主要是call和ret。汇编语言的call指令相当于执行了2步操作,分别是,1)将当前的IP或CS和IP压入栈中; 2)跳转,类似与jmp指令。同样,ret指令也分2步,分别是,1)将栈中的地址弹出到IP寄存器;2)跳转执行后续指令。这个基本上就是函数调用的原理。
除了在代码间的跳动外,函数的调用往往还需要传递一个参数,而处理完成后还可能有返回值。这些数据的传递都是通过寄存器进行的。在函数调用之前通过上文介绍的寄存器存储参数,函数返回之前通过RAX寄存器(32位系统为EAX)存储返回结果。
函数的参数是从右往左传递的。
另外一个比较重要的知识点是函数调用过程中与堆栈相关的寄存器RSP和RBP,
RSP(32位叫ESP):栈指针寄存器(reextended stack pointer),其内存放着一个指针,该指针永远指向系统栈最上面一个栈帧的栈顶。
RBP(32位叫EBP):基址指针寄存器(reextended base pointer),其内存放着一个指针,该指针永远指向系统栈最上面一个栈帧的底部。
可以看出函数内,局部变量的地址是越来越低的。rsp栈顶
到运行到call Blur时,先将main函数的栈底(高地址)push rbp。
并且将main函数的栈顶rsp作为新调用函数blur的栈底 mov rbp <- rsp。
然后把传进来的参数放在新的栈顶(rbp - 112) mov DWORD PTR [rbp-112], r9d
把函数内的局部变量放在栈底并且向上生长(rbp-8)int* pA1 = pSrc - strideS*2; mov QWORD PTR [rbp-8], rax
函数语句以及汇编指令
基本指令
指令 | 指令 | 耗时latency | Rthroughput |
---|---|---|---|
sub eax, 5 | 寄存器 - 常数 | 1 | 0.25 |
mov eax, dword ptr [rax] | 读 32位 | 5 | 0.5 |
mov rax, qword ptr [rbp - 8] | 读64位 | 5 | 0.5 |
mov qword ptr [rbp - 24], rax | 写64位 | 1 | 1 |
jmp .L3 | 1 | 0.5 | |
add rax, rdx | 寄存器相加 | 1 | 0.25 |
neg rax | 取反 | 1 | 0.25 |
shl rax, 2 | 左移 | 1 | 0.5 |
cdqe | 它用于将一个32位有符号整数(存储在 EAX 寄存器中)扩展为一个64位有符号整数(扩展到 RAX 寄存器中) | 1 | 0.25 |
lea rdx, [4*rax] | “Load Effective Address” lea destination, source | 1 | 0.5 |
C++ 语句对应指令
int f = pA1[w]; | mov eax, DWORD PTR [rbp-48] | 读w的地址 | 5 |
cdqe | 32eax 64位rax | 1 | |
lea rdx, [0+rax*4] | 读w地址对应的数据w | 1 | |
mov rax, QWORD PTR [rbp-8] | 读pA1的地址 | 5 | |
add rax, rdx | 地址偏移w | 1 | |
mov eax, DWORD PTR [rax] | 读pA1[w] 地址对应的数据 | 5 | |
mov DWORD PTR [rbp-68], eax | 写到f里 | 1 | |
int c =pA1[w] + pA1[w - 1]; | mov eax, DWORD PTR [rbp-48] | 读w的地址 | 5 |
cdqe | 32eax 64位rax | 1 | |
lea rdx, [0+rax*4] | 读w地址对应的数据w | 1 | |
mov rax, QWORD PTR [rbp-8] | 读pA1的地址 | 5 | |
add rax, rdx | 地址偏移w | 1 | |
mov edx, DWORD PTR [rax] | 读pA1[w] 地址对应的数据 | 5 | |
mov eax, DWORD PTR [rbp-48] | 读w的地址 | 5 | |
cdqe | 32eax 64位rax | 1 | |
add rax, 1 | 地址w+1 | 1 | |
lea rcx, [0+rax*4] | 读w+1地址对应的数据 | 1 | |
mov rax, QWORD PTR [rbp-8] | 读pA1的地址 | 5 | |
add rax, rcx | 地址偏移w | 1 | |
mov eax, DWORD PTR [rax] | 读pA1[w] 地址对应的数据 | 5 | |
add eax, edx | add两个数字 | 1 | |
mov DWORD PTR [rbp-56], eax | 写 | 1 |
sum = (sum * 327)>>13; |
mov eax, DWORD PTR [rbp-92] |
imul eax, eax, 327 | |
sar eax, 13 | |
mov DWORD PTR [rbp-92], eax | |
sum = sum / 25; | mov eax, DWORD PTR [rbp-92] |
(在sum最大范围数据类型最大精度下优化算法) | movsx rdx, eax |
imul rdx, rdx, 1374389535 | |
shr rdx, 32 | |
mov ecx, edx | |
sar ecx, 3 | |
cdq | |
mov eax, ecx | |
sub eax, edx | |
mov DWORD PTR [rbp-92], eax | |
pBlur[w] = static_cast |
mov eax, DWORD PTR [rbp-48] |
cdqe | |
lea rdx, [0+rax*4] | |
mov rax, QWORD PTR [rbp-104] | |
add rdx, rax | |
mov eax, DWORD PTR [rbp-92] | |
mov DWORD PTR [rdx], eax | |
for (int h = 0; h < height; h++) | mov DWORD PTR [rbp-44], 0 |
jmp .L2 | |
L2: | |
mov eax, DWORD PTR [rbp-44] | |
cmp eax, DWORD PTR [rbp-128] | |
jl .L5 |