gccはx 64システムの中でどのようにパラメータを伝達して、linux、mac、iOSは適用します
9879 ワード
前回はvc(windows)プラットフォームのx 64システムにおけるc関数のパラメータ伝達方式を紹介した.本編では、gcc(クラスlinux,mac)プラットフォームがx 64で、c関数がどのように伝達されているかについて説明します.時間と幅を節約するには、まず10個のパラメータを持つ関数を定義します.パラメータタイプには、埋め込みタイプが含まれています.
逆アセンブリ呼び出し
データ型は、浮動小数点型と非浮動小数点型の2つに分類されていることがわかります.私が伝えた実パラメータもこの2つの区分で増加しています.非浮動小数点パラメータはそれぞれ'c',0,1,2,3,(char*)0 x 4,(void**)0 x 5,(void*)6であった.まず、最初の6つの優先順位をrdi,rsi,rdx,rcx,r 8,r 9に並べます.残り(void**)5、(void*)6.浮動小数点パラメータはそれぞれ1である.f, 2.f. xmm 0,xmm 1に順番に配置します.最後に,レジスタの残りのパラメータに2種類を入れることができず,右から左へ順にスタックに入れる.
次にスーパー無敵マルチパラメータの関数を定義し、すべてのパラメータレジスタを使い果たし、私の上の分析を証明します.
逆アセンブリ呼び出し
非浮動小数点パラメータはそれぞれ'c',0,1,2,3,(char*)0 x 4,(void**)0 x 5,(void*)6であった.まず、最初の6つの優先順位をrdi,rsi,rdx,rcx,r 8,r 9に並べます.残り(void**)5、(void*)6.浮動小数点パラメータはそれぞれ1である.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f, (float)i. xmm 0−xmm 7に順番に配置し、残り(float)iとする.最後に、レジスタに入れられない2種類の残りのパラメータは、それぞれ(void*)5、(void*)6、(float)iであり、右から左へ順次スタックに入る.
最後に、本編の終了として特例を選択し、gccが一時的なオブジェクトをどのように伝達するかを選択します.
逆アセンブリ呼び出し
rdiが何であるかはよく知られていますが、残りのパラメータベクターはxmm 0です.関数定義をもう一度見てみると、パラメータは一時オブジェクトであり、オブジェクト定義を見てみると、point構造体は2つの単精浮動点で64ビットを占めている.xmmレジスタは4つの単精浮動小数点データを格納することができる.次に、メンバー関数fooの逆アセンブリを見てみましょう.
ここまで、x 64システムの3つの一般的なプラットフォームがc/c+/objcでプログラミングされるパラメータ伝達方式を3編紹介しました.前編では、lldbデバッグを通じてmacプラットフォームの下でx 64伝参を紹介した.中編では、windbgデバッグを通じてwindowsプラットフォームの下でx 64伝参を紹介する.次編では、gdbデバッグによりgcc(クラスlinux)プラットフォームの下でx 64を紹介します.本編はmac、iosにも適用されます.
予告:後で逆アセンブリ分析objcプログラムに入ります.
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>
データ型は、浮動小数点型と非浮動小数点型の2つに分類されていることがわかります.私が伝えた実パラメータもこの2つの区分で増加しています.非浮動小数点パラメータはそれぞれ'c',0,1,2,3,(char*)0 x 4,(void**)0 x 5,(void*)6であった.まず、最初の6つの優先順位をrdi,rsi,rdx,rcx,r 8,r 9に並べます.残り(void**)5、(void*)6.浮動小数点パラメータはそれぞれ1である.f, 2.f. xmm 0,xmm 1に順番に配置します.最後に,レジスタの残りのパラメータに2種類を入れることができず,右から左へ順にスタックに入れる.
次にスーパー無敵マルチパラメータの関数を定義し、すべてのパラメータレジスタを使い果たし、私の上の分析を証明します.
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*)0 x 4,(void**)0 x 5,(void*)6であった.まず、最初の6つの優先順位をrdi,rsi,rdx,rcx,r 8,r 9に並べます.残り(void**)5、(void*)6.浮動小数点パラメータはそれぞれ1である.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f, (float)i. xmm 0−xmm 7に順番に配置し、残り(float)iとする.最後に、レジスタに入れられない2種類の残りのパラメータは、それぞれ(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が何であるかはよく知られていますが、残りのパラメータベクターはxmm 0です.関数定義をもう一度見てみると、パラメータは一時オブジェクトであり、オブジェクト定義を見てみると、point構造体は2つの単精浮動点で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.
ここまで、x 64システムの3つの一般的なプラットフォームがc/c+/objcでプログラミングされるパラメータ伝達方式を3編紹介しました.前編では、lldbデバッグを通じてmacプラットフォームの下でx 64伝参を紹介した.中編では、windbgデバッグを通じてwindowsプラットフォームの下でx 64伝参を紹介する.次編では、gdbデバッグによりgcc(クラスlinux)プラットフォームの下でx 64を紹介します.本編はmac、iosにも適用されます.
予告:後で逆アセンブリ分析objcプログラムに入ります.