指定过程变量i用寄存器的问题

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直接输出机器码和汇编代码:

forcereg

 

在 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

发表评论

电子邮件地址不会被公开。 必填项已用*标注