如何获得C指令的大小?例如,我想知道,如果我在使用Intel Core2Duo处理器的Windows XP上工作,那么指令的空间是多少:
while(1==9)
{
printf("test");
}
取?
答案 0 :(得分:7)
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
语句的显着缺席。)
您可以在your favourite x86 documentation中查找指令,并查看E8
是单字节call
操作码;后续的四个字节是操作数。
答案 1 :(得分:2)
gcc
有一个extension,它将标签的地址作为void*
类型的值返回。
也许你可以将它用于你的意图。
/* UNTESTED --- USE AT YOUR OWN RISK */
labelbegin:
while (1 == 9) {
printf("test\n");
}
labelend:
printf("length: %d\n",
(int)((unsigned char *)&&labelend - (unsigned char *)&&labelbegin));
答案 2 :(得分:2)
您可以找到二进制代码块的大小,如下所示(x86 target,gcc compiler):
#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)编写的二进制代码,而不是像普通的JIT编译器那样发出汇编二进制代码。
答案 3 :(得分:0)
对于包含跟踪器的跟踪器或调试器来说,这通常是一项工作,还有一些外部工具可以检查和分析程序的内存使用情况,如valgrind。
请参阅所选IDE的文档或您选择的编译器。
答案 4 :(得分:0)
要添加以前的答案,有时您可以确定代码片段的大小 - 查看链接器生成的映射文件,您应该能够看到全局符号及其大小,包括全局函数。有关详细信息,请参阅此处:What's the use of .map files the linker produces?(对于VC ++,但evey编译器的概念类似)。