gcc가 x64 시스템에서 매개 변수를 어떻게 전달하는지,linux,mac,iOS 적용
int foo(char c, short s, int i, long l, long long ll, char* p, // 6 ,
void** pp, float f, void* x, double d);
어셈블러 호출
foo('c', 0, 1, 2, 3, (char*)0x4, (void**)0x5, 1.f, (void*)6, 2.f);
0x000000000040067b <+55>: movsd 0x2d5(%rip),%xmm0 # 0x400958 <__dso_handle+8> double d = 2.f
0x0000000000400683 <+63>: movq $0x6,0x8(%rsp) # (void*) 6
0x000000000040068c <+72>: movq $0x5,(%rsp) # (void**) 0x5
0x0000000000400694 <+80>: movapd %xmm0,%xmm1
0x0000000000400698 <+84>: movss 0x2c0(%rip),%xmm0 # 0x400960 <__dso_handle+16> float f = 1.f
0x00000000004006a0 <+92>: mov $0x4,%r9d # (char*) 0x4
0x00000000004006a6 <+98>: mov $0x3,%r8d # (long long) 3
0x00000000004006ac <+104>: mov $0x2,%ecx # (long) 2
0x00000000004006b1 <+109>: mov $0x1,%edx # (int) 1
0x00000000004006b6 <+114>: mov $0x0,%esi # (short) 0
0x00000000004006bb <+119>: mov $0x63,%edi # (char) 'c'
0x00000000004006c0 <+124>: callq 0x4005c4 <_Z3foocsilxPcPPvfS0_d>
데이터 유형은 두 종류로 나뉘는데 부동점과 비부동점형이다.내가 전하는 실제 매개 변수도 이 두 종류에 따라 점차적으로 증가한다.비부동 소수점 매개 변수는 각각'c', 0, 1, 2, 3, (char*) 0x4, (void**) 0x5, (void*) 6이다.먼저 6개의 우선순위를 rdi,rsi,rdx,rcx,r8,r9로 순서대로 배열합니다.남은 (void**) 5, (void*) 6.부동 소수점 매개 변수는 각각 1이다.f, 2.f. xmm0, xmm1로 순서대로 배치합니다.마지막으로 두 가지 종류를 레지스터에 넣을 수 없는 나머지 매개 변수를 오른쪽에서 왼쪽으로 순서대로 창고에 넣습니다.
다음은 슈퍼 무적 다중 매개 변수의 함수를 다시 정의하여 모든 전송 레지스터를 사용하여 제 분석을 증명합니다.
int foo2(char c, short s, int i, long l, long long ll, char* p,
void** pp, float f, void* x, double d, // foo
float xmm2, float xmm3, float xmm4, float xmm5, float xmm6, float xmm7, // 6
float xmmUnknow);
어셈블러 호출
foo2('c', 0, 1, 2, 3, (char*)4, (void**)5, 1.f, (void*)6, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f, (float)i);
0x00000000004006c5 <+129>: cvtsi2ssl -0xc(%rbp),%xmm0
0x00000000004006ca <+134>: movsd 0x286(%rip),%xmm1 # 0x400958 <__dso_handle+8>
0x00000000004006d2 <+142>: movss %xmm0,0x10(%rsp) # ***
0x00000000004006d8 <+148>: movq $0x6,0x8(%rsp) # *** foo
0x00000000004006e1 <+157>: movq $0x5,(%rsp) # *** foo
0x00000000004006e9 <+165>: movss 0x273(%rip),%xmm7 # 0x400964 <__dso_handle+20>
0x00000000004006f1 <+173>: movss 0x26f(%rip),%xmm6 # 0x400968 <__dso_handle+24>
0x00000000004006f9 <+181>: movss 0x26b(%rip),%xmm5 # 0x40096c <__dso_handle+28>
0x0000000000400701 <+189>: movss 0x267(%rip),%xmm4 # 0x400970 <__dso_handle+32>
0x0000000000400709 <+197>: movss 0x263(%rip),%xmm3 # 0x400974 <__dso_handle+36>
0x0000000000400711 <+205>: movss 0x25f(%rip),%xmm2 # 0x400978 <__dso_handle+40>
0x0000000000400719 <+213>: movss 0x23f(%rip),%xmm0 # 0x400960 <__dso_handle+16>
0x0000000000400721 <+221>: mov $0x4,%r9d
0x0000000000400727 <+227>: mov $0x3,%r8d
0x000000000040072d <+233>: mov $0x2,%ecx
0x0000000000400732 <+238>: mov $0x1,%edx
0x0000000000400737 <+243>: mov $0x0,%esi
0x000000000040073c <+248>: mov $0x63,%edi
0x0000000000400741 <+253>: callq 0x4005f5 <_Z4foo2csilxPcPPvfS0_dfffffff>
비부동 소수점 매개 변수는 각각'c', 0, 1, 2, 3, (char*) 0x4, (void**) 0x5, (void*) 6이다.먼저 6개의 우선순위를 rdi,rsi,rdx,rcx,r8,r9로 순서대로 배열합니다.남은 (void**) 5, (void*) 6.부동 소수점 매개 변수는 각각 1이다.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f, (float)i. xmm0-xmm7로 순서대로 배정하고 나머지는 (float)i입니다.마지막으로 두 가지 유형을 레지스터에 넣을 수 없는 나머지 매개 변수는 (void**)5, (void*)6, (float)i로 오른쪽에서 왼쪽으로 순서대로 입고됩니다.
마지막으로 나는 이 편을 끝으로 gcc가 임시 대상을 어떻게 전달하는지 특례를 선택했다.
struct point {float x,y;};
struct obj
{
int i;
float f[8];
void foo(point pt)
{
f[2] += pt.x;
f[3] *= pt.y;
}
};
어셈블러 호출
obj j;
point pt;
j.foo(pt);
0x000000000040078d <+329>: movq -0x20(%rbp),%xmm0
0x0000000000400792 <+334>: lea -0x50(%rbp),%rax
0x0000000000400796 <+338>: mov %rax,%rdi
0x0000000000400799 <+341>: callq 0x400814 <_ZN3obj3fooE5point>
rdi가 무엇인지 모두가 알고 있습니다. 나머지 매개 변수 캐리어는 xmm0입니다.다시 한 번 함수 정의를 보면 매개 변수는 임시 대상이고 대상 정의를 보면point 구조체는 두 개의 단일 부동점으로 모두 64위를 차지한다.xmm 레지스터는 4개의 단일 부동점 데이터를 저장할 수 있다.다음은 구성원 함수foo의 반집성을 보면 딱 증명된다.
Dump of assembler code for function _ZN3obj3fooE5point:
0x0000000000400814 <+0>: push %rbp
0x0000000000400815 <+1>: mov %rsp,%rbp
0x0000000000400818 <+4>: mov %rdi,-0x8(%rbp)
0x000000000040081c <+8>: movq %xmm0,-0x10(%rbp) # 64
0x0000000000400821 <+13>: mov -0x8(%rbp),%rax
0x0000000000400825 <+17>: movss 0xc(%rax),%xmm1
0x000000000040082a <+22>: movss -0x10(%rbp),%xmm0 # pt.x
0x000000000040082f <+27>: addss %xmm1,%xmm0
0x0000000000400833 <+31>: mov -0x8(%rbp),%rax
0x0000000000400837 <+35>: movss %xmm0,0xc(%rax)
0x000000000040083c <+40>: mov -0x8(%rbp),%rax
0x0000000000400840 <+44>: movss 0x10(%rax),%xmm1
0x0000000000400845 <+49>: movss -0xc(%rbp),%xmm0 # pt.y
0x000000000040084a <+54>: mulss %xmm1,%xmm0
0x000000000040084e <+58>: mov -0x8(%rbp),%rax
0x0000000000400852 <+62>: movss %xmm0,0x10(%rax)
0x0000000000400857 <+67>: leaveq
0x0000000000400858 <+68>: retq
End of assembler dump.
지금까지 저는 x64 시스템의 세 가지 상용 플랫폼이 c/c++/objc 프로그래밍에 사용되는 참조 방식을 세 편으로 소개했습니다.전편에서 lldb 디버깅을 통해 맥 플랫폼 아래 x64 전참을 소개한다.중편, windbg 디버깅을 통해 윈도우즈 플랫폼 아래 x64 전참을 소개한다.다음 편은 gdb 디버깅을 통해 gcc(클래스linux) 플랫폼에서 x64 전참을 소개하는데 이 편은 맥,ios에도 적용된다.
예고: 뒤에 어셈블리 분석objc 프로그램에 들어갈 것입니다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.