Pmason_rose 问我“VC中强制一个过程中变量i使用ebx咋写”?
VC2008下面先写一个简单的程序
#include "stdafx.h" int _tmain(int argc, _TCHAR* argv[]) { int i; for (i=0;i<10;i++) { printf("%d: www.lab-z.com\n",i); } getchar(); return 0; }
确定上面的程序可以正常编译通过之后,可以设置 Assembler Output 中,让VC2008直接输出机器码和汇编代码:
在 Debug目录下会出现 loop.cod,内容如下,可以看出使用内存变量 i 做的循环
ff lea edi, DWORD PTR [ebp-204] 00012 b9 33 00 00 00 mov ecx, 51 ; 00000033H 00017 b8 cc cc cc cc mov eax, -858993460 ; ccccccccH 0001c f3 ab rep stosd ; 9 : int i; ; 10 : ; 11 : for (i=0;i<10;i++) 0001e c7 45 f8 00 00 00 00 mov DWORD PTR _i$[ebp], 0 00025 eb 09 jmp SHORT $LN3@wmain $LN2@wmain: 00027 8b 45 f8 mov eax, DWORD PTR _i$[ebp] 0002a 83 c0 01 add eax, 1 0002d 89 45 f8 mov DWORD PTR _i$[ebp], eax $LN3@wmain: 00030 83 7d f8 0a cmp DWORD PTR _i$[ebp], 10 ; 0000000aH 00034 7d 1d jge SHORT $LN1@wmain ; 12 : { ; 13 : printf("%d: www.lab-z.com\n",i); 00036 8b f4 mov esi, esp 00038 8b 45 f8 mov eax, DWORD PTR _i$[ebp] 0003b 50 push eax 0003c 68 00 00 00 00 push OFFSET ??_C@_0BD@OPIHGHME@?$CFd?3?5www?4lab?9z?4com?6?$AA@ 00041 ff 15 00 00 00 00 call DWORD PTR __imp__printf 00047 83 c4 08 add esp, 8 0004a 3b f4 cmp esi, esp 0004c e8 00 00 00 00 call __RTC_CheckEsp ; 14 : } 00051 eb d4 jmp SHORT $LN2@wmain $LN1@wmain:
首先,使用寄存器变量试试,用register 关键字修饰 Int i; 修改程序
#include "stdafx.h"
int _tmain(int argc, _TCHAR* argv[])
{
register int i;
for (i=0;i<10;i++)
{
printf("%d: www.lab-z.com\n",i);
}
getchar();
return 0;
}
查看结果
; 9 : register int i; ; 10 : ; 11 : for (i=0;i<10;i++) 0001e c7 45 f8 00 00 00 00 mov DWORD PTR _i$[ebp], 0 00025 eb 09 jmp SHORT $LN3@wmain $LN2@wmain: 00027 8b 45 f8 mov eax, DWORD PTR _i$[ebp] 0002a 83 c0 01 add eax, 1 0002d 89 45 f8 mov DWORD PTR _i$[ebp], eax $LN3@wmain: 00030 83 7d f8 0a cmp DWORD PTR _i$[ebp], 10 ; 0000000aH 00034 7d 1d jge SHORT $LN1@wmain ; 12 : { ; 13 : printf("%d: www.lab-z.com\n",i); 00036 8b f4 mov esi, esp 00038 8b 45 f8 mov eax, DWORD PTR _i$[ebp] 0003b 50 push eax 0003c 68 00 00 00 00 push OFFSET ??_C@_0BD@OPIHGHME@?$CFd?3?5www?4lab?9z?4com?6?$AA@ 00041 ff 15 00 00 00 00 call DWORD PTR __imp__printf 00047 83 c4 08 add esp, 8 0004a 3b f4 cmp esi, esp 0004c e8 00 00 00 00 call __RTC_CheckEsp ; 14 : } 00051 eb d4 jmp SHORT $LN2@wmain
恩就是说编译器根本没有鸟我…..查看资料:
“声明为register类型的变量提示计算机这个变量应该存储于机器的硬件寄存器而不是内存中。通常,寄存器变量比存于内存中的变量访问起来效率更高。但是,编译器并不一定要理睬register关键字,如果有太多的变量被声明为register类型,那么编译器只选取前几个,将其实际存储于寄存器中,其余的就按普通变量处理。如果一个编译器自己具有一套寄存器优化方案的话,它也可能忽略register关键字,其依据是由编译器决定哪些变量春处于寄…”【参考1】
还有其他办法,就是直接插入汇编语言。修改程序如下:
// loop.cpp : Defines the entry point for the console application. // #include "stdafx.h" int _tmain(int argc, _TCHAR* argv[]) { int i; __asm { mov ebx,0 next: push ebx mov i,ebx } printf("%d: www.lab-z.com\n",i); __asm { pop ebx inc ebx cmp ebx,10 jNz next } getchar(); return 0; }
运行结果和之前的程序完全一样,对应的汇编和机器码
; 9 : int i; ; 10 : ; 11 : __asm ; 12 : { ; 13 : mov ebx,0 0001e bb 00 00 00 00 mov ebx, 0 $next$5245: ; 14 : next: ; 15 : push ebx 00023 53 push ebx ; 16 : mov i,ebx 00024 89 5d f8 mov DWORD PTR _i$[ebp], ebx ; 17 : } ; 18 : printf("%d: www.lab-z.com\n",i); 00027 8b f4 mov esi, esp 00029 8b 45 f8 mov eax, DWORD PTR _i$[ebp] 0002c 50 push eax 0002d 68 00 00 00 00 push OFFSET ??_C@_0BD@OPIHGHME@?$CFd?3?5www?4lab?9z?4com?6?$AA@ 00032 ff 15 00 00 00 00 call DWORD PTR __imp__printf 00038 83 c4 08 add esp, 8 0003b 3b f4 cmp esi, esp 0003d e8 00 00 00 00 call __RTC_CheckEsp ; 19 : __asm ; 20 : { ; 21 : pop ebx 00042 5b pop ebx ; 22 : inc ebx 00043 43 inc ebx ; 23 : cmp ebx,10 00044 83 fb 0a cmp ebx, 10 ; 0000000aH ; 24 : jNz next 00047 75 da jne SHORT $next$5245 ; 25 : }
因此,直接嵌入汇编是一个很好的解决方法。需要注意的是堆栈的平衡以及在复杂的数据结构和操作的情况下一定要保证不能干扰参数传递。
参考1:http://bbs.csdn.net/topics/300225947