2016年6月21日 星期二

c 如何傳回 struct

c 如何 return 一個 struct 呢? 我很好奇, 來看看反組譯的程式碼。

ret_struct.c
 1 #include <stdio.h>
 2 
 3 typedef struct Data_
 4 {
 5   int a;
 6   int b;
 7   char ch;
 8 }Data;
 9 
10 Data ret_data()
11 {
12   Data d;
13 
14   d.a=100;
15   d.b=200;
16   d.ch = 'a';
17 
18   return d;
19 }
20 
21 int main(int argc, char *argv[])
22 {
23   Data da = ret_data(); 
24   da.a=101;
25   return 0;
26 }


ret_struct_c.asm
 1 
 2 ret_struct_c:     file format elf32-i386
 3 
 4 
 5 Disassembly of section .init:
 6 
 7 080483db <ret_data>:
 8   int b;
 9   char ch;
10 }Data;
11 
12 Data ret_data()
13 {
14  80483db: 55                    push   %ebp
15  80483dc: 89 e5                 mov    %esp,%ebp
16  80483de: 83 ec 10              sub    $0x10,%esp
17   Data d;
18 
19   d.a=100;
20  80483e1: c7 45 f4 64 00 00 00  movl   $0x64,-0xc(%ebp)
21   d.b=200;
22  80483e8: c7 45 f8 c8 00 00 00  movl   $0xc8,-0x8(%ebp)
23   d.ch = 'a';
24  80483ef: c6 45 fc 61           movb   $0x61,-0x4(%ebp)
25 
26   return d;
27  80483f3: 8b 45 08              mov    0x8(%ebp),%eax
28  80483f6: 8b 55 f4              mov    -0xc(%ebp),%edx
29  80483f9: 89 10                 mov    %edx,(%eax)
30  80483fb: 8b 55 f8              mov    -0x8(%ebp),%edx
31  80483fe: 89 50 04              mov    %edx,0x4(%eax)
32  8048401: 8b 55 fc              mov    -0x4(%ebp),%edx
33  8048404: 89 50 08              mov    %edx,0x8(%eax)
34 }
35  8048407: 8b 45 08              mov    0x8(%ebp),%eax
36  804840a: c9                    leave  
37  804840b: c2 04 00              ret    $0x4
38 
39 0804840e <main>:
40 
41 int main(int argc, char *argv[])
42 {
43  804840e: 55                    push   %ebp
44  804840f: 89 e5                 mov    %esp,%ebp
45  8048411: 83 ec 10              sub    $0x10,%esp
46   Data da = ret_data(); 
47  8048414: 8d 45 f4              lea    -0xc(%ebp),%eax
48  8048417: 50                    push   %eax
49  8048418: e8 be ff ff ff        call   80483db <ret_data>
50   da.a=101;
51  804841d: c7 45 f4 65 00 00 00  movl   $0x65,-0xc(%ebp)
52   return 0;
53  8048424: b8 00 00 00 00        mov    $0x0,%eax
54 }
55  8048429: c9                    leave  
56  804842a: c3                    ret    
57  804842b: 66 90                 xchg   %ax,%ax
58  804842d: 66 90                 xchg   %ax,%ax
59  804842f: 90                    nop

ret_struct_c.asm L27 0x8(%ebp) 就是 ret_struct.c L23 Data da, 透過 ret_struct_c.asm L47 ~ 49 可以看出, compiler 大概轉成 m_ret_struct.c

ret_struct_c.asm L47 -0xc(%ebp) 就是 da 的位址, push 給 ret_data() 就是傳給 ret_data(), 有趣的是我們的 ret_data 並沒有接受參數, 這類似於 return value optimization。

m_ret_struct.c
1 #include <stdio.h>
 2
 3 typedef struct Data_
 4 {
 5   int a;
 6   int b;
 7   char ch;
 8 }Data;
 9
10 void ret_data(Data *d)
11 {
12     Data data;

13     data.a=100;
14     data.b=200;
15     data.ch = 'a';

24     *d = data;
25 }
26
27 int main(int argc, char *argv[])
28 {
29   Data da;
30   ret_data(&da);
31   da.a=101;
32   return 0;
33 }
  

這樣也一篇, 當然阿!

沒有留言:

張貼留言

使用 google 的 reCAPTCHA 驗證碼, 總算可以輕鬆留言了。

我實在受不了 spam 了, 又不想讓大家的眼睛花掉, 只好放棄匿名留言。這是沒辦法中的辦法了。留言的朋友需要有 google 帳號。