cpp对象基本反汇编补充

补充第七章中没提到的一些点

速记

  1. 栈中变量是先声明的在高地址,后声明的在低地址。
  2. 当成员函数参数为对象且返回对象时,先传返回的临时this,再传本对象this,再传其它参数(通过栈顶)
  3. 对象成员的存储顺序,对象内先声明的成员在低地址,后声明的在高地址
  4. 结构体数据对齐为:每个成员的地址为q(q=min(该成员类型大小,设定对齐值))的倍数。
  5. 空类对象有一字节的大小,为了让this有的指
  6. 数组与结构体为成员时,对齐不是按整体大小,按单个类型与结构体的对齐值当做成员大小去计算。这些特定编译器实现不同
  7. 临时对象的作用域仅限单条语句。

源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
class A{
public :
int a;
int b;
int c;
int d;
char e[50];
A f(A a)
{
int fa;
int fb;
int fc;
int fd;
fa=1;
fb=2;
fc=3;
fd=4;
a.a=fa;
return a;
}
};
int main(int argc, char const *argv[])
{
A a;
a.a=1;
a.b=2;
a.c=3;
A b=a.f(a);
return 0;
}

反编译

x86-64

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
.text:00000000000005E0 ; int __cdecl main(int argc, const char **argv, const char **envp)
.text:00000000000005E0 main proc near ; DATA XREF: start+2E↑o
.text:00000000000005E0
.text:00000000000005E0 var_F0 = qword ptr -0F0h
.text:00000000000005E0 var_E8 = dword ptr -0E8h
.text:00000000000005E0 var_E4 = dword ptr -0E4h
.text:00000000000005E0 var_E0 = xmmword ptr -0E0h
.text:00000000000005E0 var_D0 = xmmword ptr -0D0h
.text:00000000000005E0 var_C0 = xmmword ptr -0C0h
.text:00000000000005E0 var_B0 = xmmword ptr -0B0h
.text:00000000000005E0 var_A0 = dword ptr -0A0h
.text:00000000000005E0 src = byte ptr -98h
.text:00000000000005E0 var_50 = xmmword ptr -50h
.text:00000000000005E0 var_40 = xmmword ptr -40h
.text:00000000000005E0 var_30 = xmmword ptr -30h
.text:00000000000005E0 var_20 = xmmword ptr -20h
.text:00000000000005E0 var_10 = dword ptr -10h
.text:00000000000005E0 var_8 = qword ptr -8
.text:00000000000005E0
.text:00000000000005E0 ; __unwind {
.text:00000000000005E0 push rbp
.text:00000000000005E1 mov rbp, rsp
.text:00000000000005E4 sub rsp, 140h
.text:00000000000005EB mov rax, fs:28h
.text:00000000000005F4 mov [rbp+var_8], rax
.text:00000000000005F8 mov [rbp+var_E4], 0
.text:0000000000000602 mov [rbp+var_E8], edi
.text:0000000000000608 mov [rbp+var_F0], rsi
//这里看出对象内容排序是先声明的在低地址,后声明的在高地址。
.text:000000000000060F mov dword ptr [rbp+var_50], 1
.text:0000000000000616 mov dword ptr [rbp+var_50+4], 2
.text:000000000000061D mov dword ptr [rbp+var_50+8], 3
.text:0000000000000624 mov edi, [rbp+var_10]
.text:0000000000000627 mov [rbp+var_A0], edi
.text:000000000000062D movups xmm0, [rbp+var_40]
.text:0000000000000631 movups xmm1, [rbp+var_30]
.text:0000000000000635 movups xmm2, [rbp+var_20]
.text:0000000000000639 movaps [rbp+var_B0], xmm2
.text:0000000000000640 movaps [rbp+var_C0], xmm1
.text:0000000000000647 movaps [rbp+var_D0], xmm0
.text:000000000000064E movups xmm0, [rbp+var_50]
.text:0000000000000652 movaps [rbp+var_E0], xmm0
//向栈顶放参数a
.text:0000000000000659 mov edi, [rbp+var_A0]
.text:000000000000065F mov rax, rsp
.text:0000000000000662 mov [rax+40h], edi
.text:0000000000000665 movaps xmm0, [rbp+var_E0]
.text:000000000000066C movaps xmm1, [rbp+var_D0]
.text:0000000000000673 movaps xmm2, [rbp+var_C0]
.text:000000000000067A movaps xmm3, [rbp+var_B0]
.text:0000000000000681 movups xmmword ptr [rax+30h], xmm3
.text:0000000000000685 movups xmmword ptr [rax+20h], xmm2
.text:0000000000000689 movups xmmword ptr [rax+10h], xmm1
.text:000000000000068D movups xmmword ptr [rax], xmm0
//rdi是返回地址 rsi是this
.text:0000000000000690 lea rdi, [rbp+src] ; src
.text:0000000000000697 lea rsi, [rbp+var_50]
.text:000000000000069B call sub_6D0
.text:00000000000006A0 mov rax, fs:28h
.text:00000000000006A9 mov rsi, [rbp+var_8]
.text:00000000000006AD cmp rax, rsi
.text:00000000000006B0 jnz loc_6C1
.text:00000000000006B6 xor eax, eax
.text:00000000000006B8 add rsp, 140h
.text:00000000000006BF pop rbp
.text:00000000000006C0 retn
.text:00000000000006C1 ; ---------------------------------------------------------------------------
.text:00000000000006C1
.text:00000000000006C1 loc_6C1: ; CODE XREF: main+D0↑j
.text:00000000000006C1 call ___stack_chk_fail
.text:00000000000006C1 ; } // starts at 5E0
.text:00000000000006C1 main endp

f

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
.text:00000000000006D0 ; __int64 __fastcall sub_6D0(char src)
.text:00000000000006D0 sub_6D0 proc near ; CODE XREF: main+BB↑p
.text:00000000000006D0
.text:00000000000006D0 var_20 = qword ptr -20h
.text:00000000000006D0 var_18 = dword ptr -18h
.text:00000000000006D0 var_14 = dword ptr -14h
.text:00000000000006D0 var_10 = dword ptr -10h
.text:00000000000006D0 var_C = dword ptr -0Ch
.text:00000000000006D0 var_8 = qword ptr -8
.text:00000000000006D0 src = byte ptr 10h
.text:00000000000006D0
.text:00000000000006D0 ; __unwind {
.text:00000000000006D0 push rbp
.text:00000000000006D1 mov rbp, rsp
.text:00000000000006D4 sub rsp, 20h
.text:00000000000006D8 mov rax, rdi //di是返回的临时地址
.text:00000000000006DB lea rcx, [rbp+src] //参数是用栈传递的
.text:00000000000006DF mov edx, 44h ; 'D' ; n
//栈中先声明的在高处,后声明的在低处
.text:00000000000006E4 mov [rbp+var_8], rsi
.text:00000000000006E8 mov [rbp+var_C], 1
.text:00000000000006EF mov [rbp+var_10], 2
.text:00000000000006F6 mov [rbp+var_14], 3
.text:00000000000006FD mov [rbp+var_18], 4
.text:0000000000000704 mov r8d, [rbp+var_C]
.text:0000000000000708 mov [rcx], r8d
.text:000000000000070B mov rsi, rcx ; src
.text:000000000000070E mov [rbp+var_20], rax
.text:0000000000000712 call _memcpy
.text:0000000000000717 mov rax, [rbp+var_20]
.text:000000000000071B add rsp, 20h
.text:000000000000071F pop rbp
.text:0000000000000720 retn
.text:0000000000000720 ; } // starts at 6D0
.text:0000000000000720 sub_6D0 endp
.text:0000000000000720

ARM-64

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
.text:0000000000000738 ; int __cdecl main(int argc, const char **argv, const char **envp)
.text:0000000000000738 EXPORT main
.text:0000000000000738 main ; DATA XREF: LOAD:00000000000003F0↑o
.text:0000000000000738 ; .got:main_ptr↓o
.text:0000000000000738
.text:0000000000000738 var_100 = -0x100
.text:0000000000000738 var_F8 = -0xF8
.text:0000000000000738 var_F4 = -0xF4
.text:0000000000000738 var_F0 = -0xF0
.text:0000000000000738 var_A8 = -0xA8
.text:0000000000000738 var_60 = -0x60
.text:0000000000000738 var_5C = -0x5C
.text:0000000000000738 var_58 = -0x58
.text:0000000000000738 var_18 = -0x18
.text:0000000000000738 var_10 = -0x10
.text:0000000000000738 var_s0 = 0
.text:0000000000000738
.text:0000000000000738 ; __unwind {
.text:0000000000000738 SUB SP, SP, #0x110
.text:000000000000073C STR X28, [SP,#0x100+var_10]
.text:0000000000000740 STP X29, X30, [SP,#0x100+var_s0]
.text:0000000000000744 ADD X29, SP, #0x100
.text:0000000000000748 MOV X2, #0x44
.text:000000000000074C SUB X8, X29, #-var_60
.text:0000000000000750 ADD X9, SP, #0x100+var_F0
.text:0000000000000754 MOV W10, #3
.text:0000000000000758 MOV W11, #2
.text:000000000000075C MOV W12, #1
.text:0000000000000760 MRS X13, #3, c13, c0, #2
.text:0000000000000764 LDR X13, [X13,#0x28]
.text:0000000000000768 STUR X13, [X29,#var_18]
.text:000000000000076C STR WZR, [SP,#0x100+var_F4]
.text:0000000000000770 STR W0, [SP,#0x100+var_F8]
.text:0000000000000774 STR X1, [SP,#0x100+var_100]
// var_60为a的地址
.text:0000000000000778 STUR W12, [X29,#var_60]
.text:000000000000077C STUR W11, [X29,#var_5C]
.text:0000000000000780 STUR W10, [X29,#var_58]
// 拷贝 var_60到var_F0
.text:0000000000000784 MOV X0, X9
.text:0000000000000788 MOV X1, X8
.text:000000000000078C BL .memcpy
// X8为返回地址 x0为this x1为传入的参的this
.text:0000000000000790 ADD X8, SP, #0x100+var_A8
.text:0000000000000794 SUB X0, X29, #-var_60
.text:0000000000000798 ADD X1, SP, #0x100+var_F0
.text:000000000000079C BL sub_7D0
.text:00000000000007A0 MRS X8, #3, c13, c0, #2
.text:00000000000007A4 LDR X8, [X8,#0x28]
.text:00000000000007A8 LDUR X9, [X29,#var_18]
.text:00000000000007AC CMP X8, X9
.text:00000000000007B0 B.NE loc_7CC
.text:00000000000007B4 MOV W8, WZR
.text:00000000000007B8 MOV W0, W8
.text:00000000000007BC LDP X29, X30, [SP,#0x100+var_s0]
.text:00000000000007C0 LDR X28, [SP,#0x100+var_10]
.text:00000000000007C4 ADD SP, SP, #0x110
.text:00000000000007C8 RET
.text:00000000000007CC ; ---------------------------------------------------------------------------
.text:00000000000007CC
.text:00000000000007CC loc_7CC ; CODE XREF: main+78↑j
.text:00000000000007CC BL .__stack_chk_fail
.text:00000000000007CC ; } // starts at 738
.text:00000000000007CC ; End of function main
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
.text:00000000000007D0 sub_7D0 ; CODE XREF: main+64↑p
.text:00000000000007D0
.text:00000000000007D0 var_18 = -0x18
.text:00000000000007D0 var_14 = -0x14
.text:00000000000007D0 var_10 = -0x10
.text:00000000000007D0 var_C = -0xC
.text:00000000000007D0 var_8 = -8
.text:00000000000007D0 var_s0 = 0
.text:00000000000007D0
.text:00000000000007D0 ; __unwind {
.text:00000000000007D0 SUB SP, SP, #0x30
.text:00000000000007D4 STP X29, X30, [SP,#0x20+var_s0]
.text:00000000000007D8 ADD X29, SP, #0x20
.text:00000000000007DC MOV X2, #0x44
.text:00000000000007E0 MOV W9, #4
.text:00000000000007E4 MOV W10, #3
.text:00000000000007E8 MOV W11, #2
.text:00000000000007EC MOV W12, #1
.text:00000000000007F0 STUR X0, [X29,#var_8]
// 栈高到低分配
.text:00000000000007F4 STUR W12, [X29,#var_C]
.text:00000000000007F8 STR W11, [SP,#0x20+var_10]
.text:00000000000007FC STR W10, [SP,#0x20+var_14]
.text:0000000000000800 STR W9, [SP,#0x20+var_18]
.text:0000000000000804 LDUR W9, [X29,#var_C]
//为传入的参赋值
.text:0000000000000808 STR W9, [X1]
// 拷贝x1到x8 x8为返回传入寄存器
.text:000000000000080C MOV X0, X8
.text:0000000000000810 BL .memcpy
.text:0000000000000814 LDP X29, X30, [SP,#0x20+var_s0]
.text:0000000000000818 ADD SP, SP, #0x30
.text:000000000000081C RET
.text:000000000000081C ; } // starts at 7D0
.text:000000000000081C ; End of function sub_7D0
.text:000000000000081C
.text:000000000000081C ; .text ends
.text:000000000000081C