
以下のfuncTest.cを、
int add(int a, int b) {
int array[16];
array[0] = a;
return a + b;
}
void func(void) {
int r;
r = add(7, 5);
}
gcc -c -m32 funcTest.c
でコンパイルし、funcTets.oのオブジェクトファイルを生成し、
objdump -d funcTest.o
で逆アセンブルすると、以下の出力となるのですが、
funcTest.o: file format elf32-i386
Disassembly of section .text:
00000000 <add>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 83 ec 40 sub $0x40,%esp
6: e8 fc ff ff ff call 7 <add+0x7>
b: 05 01 00 00 00 add $0x1,%eax
10: 8b 45 08 mov 0x8(%ebp),%eax
13: 89 45 c0 mov %eax,-0x40(%ebp)
16: 8b 55 08 mov 0x8(%ebp),%edx
19: 8b 45 0c mov 0xc(%ebp),%eax
1c: 01 d0 add %edx,%eax
1e: c9 leave
1f: c3 ret
00000020 <func>:
20: 55 push %ebp
21: 89 e5 mov %esp,%ebp
23: 83 ec 10 sub $0x10,%esp
26: e8 fc ff ff ff call 27 <func+0x7>
2b: 05 01 00 00 00 add $0x1,%eax
30: 6a 05 push $0x5
32: 6a 07 push $0x7
34: e8 fc ff ff ff call 35 <func+0x15>
39: 83 c4 08 add $0x8,%esp
3c: 89 45 fc mov %eax,-0x4(%ebp)
3f: 90 nop
40: c9 leave
41: c3 ret
Disassembly of section .text.__x86.get_pc_thunk.ax:
00000000 <__x86.get_pc_thunk.ax>:
0: 8b 04 24 mov (%esp),%eax
3: c3 ret
以前は、
6、b行の
call 7 <add+0x7>
add $0x1,%eax
と、
26、2b行の
call 27 <func+0x7>
add $0x1,%eax
が無くて、
34、39行の
call 35 <func+0x15>
add $0x8,%esp
が、
call 0 <add>
となって、
call命令で<add>の最初の命令を呼び出していたのですが、
何故、この様な出力になってしまったのか分かりかねています。
どなたか分かる方、御教示おください。
No.3ベストアンサー
- 回答日時:
オブジェクトファイルを逆アセするんじゃなくって, gcc に直接アセンブリ出力を出させれば 3つのうち 1つは意味がわかる.
あと, 自分で調べることも必要だと思う.
調べてみたんですけど、gccはデフォルトで、-O0オプションとなるようで、
この場合、コンパイラが「位置に依存しない」実行可能ファイルを生成するみたいです。
call __x86.get_pc_thunk.ax
はそのための「グローバルポインタ」を設定するためのものの様です。
これは、
-fno-pie
オプションをつけることで、位置に依存しない形で無くすことができる様です。
また、callの後の、
add $0x8, %esp
はfuncのスタックフレームの上限のスタックポインタの位置を仮引数を渡すために使った、5と7の2個はもう必要ないので、+8しているみたいです。
No.5
- 回答日時:
うん, そこの
fc ff ff ff
は現状「バイトを埋める」だけのダミーで, 最終的にはその飛び先である関数 add の先頭アドレス (の相対値) が入ることになる. それを入れるのはリンカかローダーのどっちかなんだけど, この場合どっちなんだろう.
そもそも同じオブジェクトファイルの中で呼んでいるだけだから, そこをダミーにする必然性はないわけだけど.
あと, 念のため改めて書いておくけどこの辺の話は C という言語とは関係なくって, 使っているシステムに依存することだからね. ここではたまたまあなたが C を使っていて疑問に思ったというだけであって, 「C だったらどのシステムでも同じようになっている」というわけではないよ.
No.4
- 回答日時:
「デフォルトで最適化オプション -O0 がつく」ことと「PIC なコードを吐く」こととは無関係だよ. -O0 以外の最適化オプショ
ンでも, -fno-pie オプションを付けないと PIC なコードになる.call 35 <func+0x15>
って、この位置のfc ff ff ffに
<add>の飛び先番地が入るってことなのですかね?
No.2
- 回答日時:
そこまで細かい話は当然ながら C の規格では一切触れられていないので, 本当に理由を知りたければ最低限「あなたが使っているシステムの詳細」は必須だろう. 「以前」のシステムはどうであって, 「今」のシステムはどうなのか, その情報がなければ答えようがない.
もちろんそれらの情報があれば確実に (誰かが) 答えてくれる, というものでもないわけだが.
あるいは, オブジェクトファイルを使わず gcc にアセンブリ出力を直接出させてみるとか.
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
このQ&Aを見た人はこんなQ&Aも見ています
-
プロが教える店舗&オフィスのセキュリティ対策術
中・小規模の店舗やオフィスのセキュリティセキュリティ対策について、プロにどう対策すべきか 何を注意すべきかを教えていただきました!
-
関数ポインタの高速化のメリット
C言語・C++・C#
-
int16_t の _t は何?
C言語・C++・C#
-
プログラミング 2つの整数を読み込んで、等しければ 「二つの値は同じです」と表示し、そうでなければ,
C言語・C++・C#
-
-
4
Cのdoubleの浮動小数点表示について
C言語・C++・C#
-
5
大量のデータを読み込んで表示する速度を改善したい
C言語・C++・C#
-
6
プログラミング 素数か素数ではないか判断するプログラミングで、写真のようなプログラミングを打ったとき
C言語・C++・C#
-
7
Cの関数の引数のconst *charについて
C言語・C++・C#
-
8
いまc言語の標準ライブラリ文字列を勉強しているのですがいまいちわかりません。 strcmpとmemc
C言語・C++・C#
-
9
Javaって使いますか、もう古いですか?C++とどっちがいいですか?分析でC++使う授業ありましたけ
C言語・C++・C#
-
10
c言語
C言語・C++・C#
-
11
スタックフレームの消滅
C言語・C++・C#
-
12
アセンブラ指令
C言語・C++・C#
-
13
【C言語】全角文字の配列を、全角のまま1文字ずつ出力する方法
C言語・C++・C#
-
14
変数のスコープ
C言語・C++・C#
-
15
C言語でファクト関数を使わずに階乗を計算する方法はありますか?できれば教えてください
C言語・C++・C#
-
16
C言語 1から20までの逆数の和を求めたいのですが、このようにプログラミングしたら値が負になってしま
C言語・C++・C#
-
17
双方向リスト
C言語・C++・C#
-
18
C言語の質問です。バイナリ形式で保存されたWindows Bitmap形式の画像ファイルを読み込み、
C言語・C++・C#
-
19
C言語について。
C言語・C++・C#
-
20
プログラミング 2つの整数を読み込んで、等しければ 「二つの値は同じです」と表示し、そうでなければ,
C言語・C++・C#
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
擬似コード 長さがmの配列でな...
-
C言語って古いですか?
-
C言語について。
-
C言語について。
-
C言語について。
-
C言語について。
-
#include <stdio.h> #include <...
-
C言語について
-
C言語について。
-
パイソン。If elseの挙動につい...
-
TCP/IP通信時のサーバーからの受信
-
Windows Formアプリからコンソ...
-
c言語でイベントフラグを使った...
-
win10で、正確な待ち時間の作り方
-
バッファリングについて。
-
C言語
-
スタックフレームの消滅
-
【C言語】全角文字の配列を、全...
-
C言語初心者です、、、お助けく...
-
C言語階乗の総和を求める
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
C言語関数違いについて。
-
C言語について。
-
ストリーム 意味について。
-
C言語について。
-
C言語 解答について。
-
バッファリングについて。
-
#include <stdio.h> #include <...
-
これを教えてください
-
C言語について。
-
C言語 バッファについて。
-
C言語 ストリームについて。
-
擬似コード
-
#include <stdio.h> #include <...
-
c#のTLS1.2での通信について
-
擬似コード
-
サブルーチンを使った再帰的な...
-
C#でゲームのチートを作ること...
-
C# でソフト開発をした事のある...
-
TCP/IP通信時のサーバーからの受信
-
大量のデータを読み込んで表示...
おすすめ情報
リリースモードでコンパイルした場合、
gcc -c -m32 funcTest.c
はどの様に書けばいいのでしょうか?
3つのcall命令は何をしているか分かりますか?
それは既にやっているのですが、
何故、最後のcall命令だけが、call add
になって、それ以外の2つが、
call __x86.get_pc_thunk.ax
になるんですかね?
また、__x86.get_pc_thunk.axに飛んで行っている、
move (%esp), %eax
って何をやっているんでしょうか?
また、call命令を行った後の、
addl $_GLOBAL_OFFSET_TABLE_, %eax
や
addl $8, %esp
も何をやっているんでしょうね?