如何获得 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
是单字节call
操作码;随后的四个字节是操作数。
gcc
有一个扩展,它将标签的地址作为 type 的值返回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));
您可以找到如下二进制代码块的大小(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) 编写的二进制代码,而不是像普通的 JIT 编译器那样发出汇编二进制代码。
它通常是跟踪器或包含跟踪器的调试器的工作,还有一些外部工具可以检查和分析程序的内存使用情况,如 valgrind。
请参阅您选择的 IDE 或您选择的编译器的文档。
要添加以前的答案,在某些情况下您可以确定代码片段的大小 - 查看链接器生成的映射文件,您应该能够在那里看到全局符号及其大小,包括全局函数。有关更多信息,请参见此处:链接器生成的 .map 文件有什么用?(对于 VC++,但对于evey 编译器的概念是相似的)。