从汇编代码看c++基础数据类型 的数组参数传递
double数组
void test(double arr1[],int n){
for (size_t i = 0; i < n; i++)
{
arr1[i] = i * 2;
}
};
int main(){
double * arr = new double[10];
for (size_t i = 0; i < 10; i++)
{
arr[i] = i;
}
test(arr,10);
return 0;
}
main函数汇编
Dump of assembler code for function main():
0x0000555555556334 <+0>: endbr64
0x0000555555556338 <+4>: push rbp
0x0000555555556339 <+5>: mov rbp,rsp
0x000055555555633c <+8>: sub rsp,0x10 //上面代码给main 分配栈空间
0x0000555555556340 <+12>: mov edi,0x50
0x0000555555556345 <+17>: call 0x555555556110 <_Znam@plt> //创建数组 并把内存地址 放入rax中 operator new[](unsigned long)
0x000055555555634a <+22>: mov QWORD PTR [rbp-0x8],rax //把数组地址备份在[rbp-0x8]
0x000055555555634e <+26>: mov QWORD PTR [rbp-0x10],0x0
0x0000555555556356 <+34>: cmp QWORD PTR [rbp-0x10],0x9
0x000055555555635b <+39>: ja 0x5555555563a1 <main()+109>
0x000055555555635d <+41>: mov rax,QWORD PTR [rbp-0x10]
0x0000555555556361 <+45>: lea rdx,[rax*8+0x0]
0x0000555555556369 <+53>: mov rax,QWORD PTR [rbp-0x8]
0x000055555555636d <+57>: lea rcx,[rdx+rax*1]
0x0000555555556371 <+61>: mov rax,QWORD PTR [rbp-0x10]
0x0000555555556375 <+65>: test rax,rax
0x0000555555556378 <+68>: js 0x555555556381 <main()+77>
0x000055555555637a <+70>: cvtsi2sd xmm0,rax
0x000055555555637f <+75>: jmp 0x555555556396 <main()+98>
0x0000555555556381 <+77>: mov rdx,rax
0x0000555555556384 <+80>: shr rdx,1
0x0000555555556387 <+83>: and eax,0x1
0x000055555555638a <+86>: or rdx,rax
0x000055555555638d <+89>: cvtsi2sd xmm0,rdx
0x0000555555556392 <+94>: addsd xmm0,xmm0
0x0000555555556396 <+98>: movsd QWORD PTR [rcx],xmm0
0x000055555555639a <+102>: add QWORD PTR [rbp-0x10],0x1
0x000055555555639f <+107>: jmp 0x555555556356 <main()+34> //上面是main函数中数组赋值 不关注
0x00005555555563a1 <+109>: mov rax,QWORD PTR [rbp-0x8] //把备份在[rbp-0x8]数组地址 取出 放入 rax
0x00005555555563a5 <+113>: mov esi,0xa //把10放入esi test函数的第二个参数
0x00005555555563aa <+118>: mov rdi,rax //把数组地址放入rdi test函数的第一个参数
0x00005555555563ad <+121>: call 0x5555555562c9 <test(double*, int)>
0x00005555555563b2 <+126>: mov eax,0x0
0x00005555555563b7 <+131>: leave
0x00005555555563b8 <+132>: ret
test函数汇编
Dump of assembler code for function test(double*, int):
0x00005555555562c9 <+0>: endbr64
0x00005555555562cd <+4>: push rbp //备份上个函数的基址指针
0x00005555555562ce <+5>: mov rbp,rsp //更新新的基址指针为rsp 相当于给画个分界线
0x00005555555562d1 <+8>: mov QWORD PTR [rbp-0x18],rdi //rdi是函数调用的第一个参数 取出来放入[rbp-0x18] 每个函数独立的rbp
0x00005555555562d5 <+12>: mov DWORD PTR [rbp-0x1c],esi //esi是函数调用的第二个参数 取出来放入[rbp-0x1c] 注每个函数独立的rbp
0x00005555555562d8 <+15>: mov QWORD PTR [rbp-0x8],0x0 //[rbp-0x8] 等价于c++代码中的局部变量i
0x00005555555562e0 <+23>: mov eax,DWORD PTR [rbp-0x1c]
0x00005555555562e3 <+26>: cdqe
0x00005555555562e5 <+28>: cmp QWORD PTR [rbp-0x8],rax //这个指令是循环控制的条件
0x00005555555562e9 <+32>: jae 0x555555556331 <test(double*, int)+104> //如果i >= rax(传递的第二个参数)则跳转,否则 向下执行
0x00005555555562eb <+34>: mov rax,QWORD PTR [rbp-0x8]
0x00005555555562ef <+38>: add rax,rax //这边等效于执行了 i*2 存放的临时计算结果
0x00005555555562f2 <+41>: mov rdx,QWORD PTR [rbp-0x8]
0x00005555555562f6 <+45>: lea rcx,[rdx*8+0x0] //这个代码作用实现指针增加的作用 rcx 存入的相对数组首地址的相对偏移量
0x00005555555562fe <+53>: mov rdx,QWORD PTR [rbp-0x18]
0x0000555555556302 <+57>: add rcx,rdx //这边rcx 里面存入的就是具体数组元素的地址了
0x0000555555556305 <+60>: test rax,rax //错误检测 如果结果为负数 则执行 72到102行逻辑
0x0000555555556308 <+63>: js 0x555555556311 <test(double*, int)+72>
0x000055555555630a <+65>: cvtsi2sd xmm0,rax
0x000055555555630f <+70>: jmp 0x555555556326 <test(double*, int)+93> //无条件跳转
0x0000555555556311 <+72>: mov rdx,rax
0x0000555555556314 <+75>: shr rdx,1
0x0000555555556317 <+78>: and eax,0x1
0x000055555555631a <+81>: or rdx,rax
0x000055555555631d <+84>: cvtsi2sd xmm0,rdx
0x0000555555556322 <+89>: addsd xmm0,xmm0
0x0000555555556326 <+93>: movsd QWORD PTR [rcx],xmm0
0x000055555555632a <+97>: add QWORD PTR [rbp-0x8],0x1
0x000055555555632f <+102>: jmp 0x5555555562e0 <test(double*, int)+23>
0x0000555555556331 <+104>: nop
0x0000555555556332 <+105>: pop rbp //恢复调用函数基址指针
0x0000555555556333 <+106>: ret //恢复调用函数ip
结论: double数组没有复制,函数间通过指针传递,共用相同的数据