函数与汇编

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(sum); 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

https://godbolt.org/