
はじめに
c言語 ポインタ完全制覇(2001年出版version)を読んでいて,本と違った動きをしたので,理由が知りたいです.
やっていること
以下のコードは関数を呼び出し,仮引数がスタックにしまわれる順番を見ています.
また,スタックに積まれる様子を見たかったので,3回だけ再帰にしています.
c
1#include <stdio.h> 2 3void some_func(int i, int a, int b) 4{ 5 printf("some_func%d..&a: %p\n", i, &a); 6 printf("some_func%d..&b: %p\n", i, &b); 7 if (i > 3) { 8 printf("end\n"); 9 } else { 10 some_func(i+1, a, b); 11 } 12} 13 14int main() { 15 int a, b; 16 some_func(0, a, b); 17 return 0; 18}
期待した結果
本では仮引数bがはじめにスタックにしまわれ,その後に仮引数aがスタックにしまわれると書いてあった.
すなわち,宣言の順番の逆順にスタックにしまわれる.
実際の結果
以下に示すように,仮引数aからスタックにしまわれる.
terminal
1$./sample 2some_func0..&a: 0x7ffee9a590f8 3some_func0..&b: 0x7ffee9a590f4 4some_func1..&a: 0x7ffee9a590c8 5some_func1..&b: 0x7ffee9a590c4 6some_func2..&a: 0x7ffee9a59098 7some_func2..&b: 0x7ffee9a59094 8some_func3..&a: 0x7ffee9a59068 9some_func3..&b: 0x7ffee9a59064 10some_func4..&a: 0x7ffee9a59038 11some_func4..&b: 0x7ffee9a59034 12end
試したこと・考えたこと
gccとclangを両方試しましたが,両方ともアドレスは仮引数aのほうが大きくなった.
コンパイラによってメモリへのしまい方が異なるのかもしれない?
中級以上の本を読むのが初めてなので,知らない知識がありそう.
補足情報(バージョンなど)
試した環境は以下のとおりです.
MacOX Mojave 10.14.1
gcc
1$gcc -v 2Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/usr/include/c++/4.2.1 3Apple LLVM version 10.0.0 (clang-1000.11.45.5) 4Target: x86_64-apple-darwin18.2.0 5Thread model: posix 6InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
clang
1Apple LLVM version 10.0.0 (clang-1000.11.45.5) 2Target: x86_64-apple-darwin18.2.0 3Thread model: posix 4InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
追記
コードをシンプルなものに変えて実行しました.
C
1#include <stdio.h> 2 3void __cdecl some_func( 4 int a, int b, int c, int d, int e, int f, int g, int h, int i, int j 5) {} // do nothing 6 7int main() { 8 some_func(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); 9 return 0; 10}
アセンブリは以下のようになりました.(一部略)
sample.s
1_some_func: 2 . 3 . 4 . 5 movl 40(%rbp), %eax 6 movl 32(%rbp), %r10d 7 movl 24(%rbp), %r11d 8 movl 16(%rbp), %ebx 9 movl %edi, -12(%rbp) 10 movl %esi, -16(%rbp) 11 movl %edx, -20(%rbp) 12 movl %ecx, -24(%rbp) 13 movl %r8d, -28(%rbp) 14 movl %r9d, -32(%rbp) 15 movl %ebx, -36(%rbp) ## 4-byte Spill 16 movl %r10d, -40(%rbp) ## 4-byte Spill 17 movl %r11d, -44(%rbp) ## 4-byte Spill 18 movl %eax, -48(%rbp) ## 4-byte Spill 19 . 20 . 21 . 22_main: 23 . 24 . 25 . 26 movl $1, %edi 27 movl $2, %esi 28 movl $3, %edx 29 movl $4, %ecx 30 movl $5, %r8d 31 movl $6, %r9d 32 movl $7, %eax 33 movl $8, %r10d 34 movl $9, %r11d 35 movl $10, %ebx 36 movl $0, -12(%rbp) 37 movl $7, (%rsp) 38 movl $8, 8(%rsp) 39 movl $9, 16(%rsp) 40 movl $10, 24(%rsp) 41 movl %ebx, -16(%rbp) ## 4-byte Spill 42 movl %r11d, -20(%rbp) ## 4-byte Spill 43 movl %r10d, -24(%rbp) ## 4-byte Spill 44 movl %eax, -28(%rbp) ## 4-byte Spill 45 callq _some_func
アセンブラについて詳しくないのですが,確かにすぐにスタックにしまっているわけではないみたいです.
これは結局最後の4つだけ右からスタックにしまっているということで大丈夫ですか?

回答3件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/12/04 15:46
退会済みユーザー
2018/12/04 17:05
2018/12/04 17:22
退会済みユーザー
2018/12/05 00:32