C命令のサイズをどのように取得しますか? たとえば、Intel Core2Duo プロセッサを搭載した Windows XP で作業している場合、命令を実行するスペースの量を知りたいです。
while(1==9)
{
printf("test");
}
かかりますか?
C命令のサイズをどのように取得しますか? たとえば、Intel Core2Duo プロセッサを搭載した Windows XP で作業している場合、命令を実行するスペースの量を知りたいです。
while(1==9)
{
printf("test");
}
かかりますか?
Cには「命令のサイズ」の概念は言うまでもなく「命令」の概念がないため、「Cでのプログラミング」のコンテキストでは質問は意味がありません。
C プログラムの基本要素はステートメントであり、任意に複雑にすることができます。
実装の詳細に関心がある場合は、コンパイラが生成するマシン コードを調べてください。これは機械語命令に分類されており、通常、各命令をエンコードするのに必要なバイト数を確認できます。
たとえば、プログラムをコンパイルします
#include <cstdio>
int main() { for (;;) std::printf("test"); }
と
g++ -c -o /tmp/out.o /tmp/in.cpp
と逆アセンブル
objdump -d /tmp/out.o -Mintel
そして私は得る:
00000000 <main>:
0: 55 push ebp
1: 89 e5 mov ebp,esp
3: 83 e4 f0 and esp,0xfffffff0
6: 83 ec 10 sub esp,0x10
9: c7 04 24 00 00 00 00 mov DWORD PTR [esp],0x0
10: e8 fc ff ff ff call 11 <main+0x11>
15: eb f2 jmp 9 <main+0x9>
ご覧のとおりcall
、私の場合、命令には 5 バイト、ループのジャンプには 2 バイトが必要です。(また、ステートメントの顕著な欠如にも注意してください。)ret
お気に入りの x86 ドキュメントで命令を調べて、それE8
が 1 バイトのcall
オペコードであることを確認できます。後続の 4 バイトはオペランドです。
次のようなバイナリ コード ブロックのサイズを確認できます (x86 ターゲット、gcc コンパイラ)。
#define CODE_BEGIN(name) __asm__ __volatile__ ("jmp ."name"_op_end\n\t""."name"_op_begin:\n\t")
#define CODE_END(name) __asm__ __volatile__ ("."name"_op_end:\n\t""movl $."name"_op_begin, %0\n\t""movl $."name"_op_end, %1\n\t":"=g"(begin), "=g"(end));
void func() {
unsigned int begin, end;
CODE_BEGIN("func");
/* ... your code goes here ... */
CODE_END("func");
printf("Code length is %d\n", end - begin);
}
この手法は、通常の JIT コンパイラのようにアセンブリ バイナリ コードを出力するのではなく、高級言語 (C) で記述されたバイナリ コードをコピーする "lazy JIT" コンパイラで使用されます。
以前の回答に追加するために、コード片のサイズを決定できる場合があります-リンカーによって生成されたマップファイルを調べてください。グローバル関数を含むグローバルシンボルとそのサイズを確認できるはずです。詳細については、こちらを参照してください:リンカーが生成する .map ファイルの用途は何ですか? (VC++ の場合ですが、概念はすべてのコンパイラで似ています)。
これは通常、トレーサーまたはトレーサーを含むデバッガーの仕事です。また、valgrind のようなプログラムのメモリ使用量を検査およびプロファイリングできる外部ツールもあります。
選択した IDE または選択したコンパイラのドキュメントを参照してください。