汇编指令优化惹的祸之 JS 跳转指令

首先看到以下代码

 

#include "stdafx.h"


int _tmain(int argc, _TCHAR* argv[])
{
	long a = 2;
	unsigned long b =10;
    a = b+6; 

    if (a>=0)
	{
		printf("a=%ld",a);
		printf("b=%u",b-1);
	}

	if (a<=0)
	{
		printf("a=%ld",a);
		printf("b=%u",b-1);
	}
	
	return 0;
}


 

UT时想改值测试,debug时第一个if处a改为-1后2个if条件都会走,奇怪?

 

一开始想跟unsigned long 转long有关系.不同类型的数在一起运算,必然会让编译器将它们划为同一类型再进行计算。这种类型间的自动转化标准,被称作Usual arithmetic conversions。下面是摘自MSDN上关于它的说明[4]:

http://msdn.microsoft.com/zh-cn/library/09ka8bxx(VS.90).aspx

但b改为long型也不行。

 

有经验同事让看看汇编实现,结果确实就慢慢明亮了。。。

 

	long a = 2;
00411A4E  mov         dword ptr [a],2 
	unsigned long b =10;
00411A55  mov         dword ptr [b],0Ah 
    a = b+6; 
00411A5C  mov         eax,dword ptr [b] 
00411A5F  add         eax,6 
00411A62  mov         dword ptr [a],eax 

    if (a>=0)
00411A65  js          main+5Ch (411A8Ch) 
	{
		printf("a=%ld",a);
00411A67  mov         eax,dword ptr [a] 
00411A6A  push        eax  
00411A6B  push        offset string "a=%ld" (4240D0h) 
00411A70  call        @ILT+1170(_printf) (411497h) 
00411A75  add         esp,8 
		printf("b=%u",b-1);
00411A78  mov         eax,dword ptr [b] 
00411A7B  sub         eax,1 
00411A7E  push        eax  
00411A7F  push        offset string "b=%u" (4240C8h) 
00411A84  call        @ILT+1170(_printf) (411497h) 
00411A89  add         esp,8 
	}

	if (a<=0)
00411A8C  cmp         dword ptr [a],0 
00411A90  jg          main+87h (411AB7h) 
	{
		printf("a=%ld",a);
00411A92  mov         eax,dword ptr [a] 
00411A95  push        eax  
00411A96  push        offset string "a=%ld" (4240D0h) 
00411A9B  call        @ILT+1170(_printf) (411497h) 
00411AA0  add         esp,8 
		printf("b=%u",b-1);
00411AA3  mov         eax,dword ptr [b] 
00411AA6  sub         eax,1 
00411AA9  push        eax  
00411AAA  push        offset string "b=%u" (4240C8h) 
00411AAF  call        @ILT+1170(_printf) (411497h) 
00411AB4  add         esp,8 
	}



细看3个地方

------------------------------------------------------------------------

1)

    a = b+6;
00411A5C  mov         eax,dword ptr [b]
00411A5F  add         eax,6
00411A62  mov         dword ptr [a],eax 

2)

    if (a>=0)
00411A65  js          main+5Ch (411A8Ch)
 {
  printf("a=%ld",a);


3)

 if (a<=0)
00411A8C  cmp         dword ptr [a],0
00411A90  jg          main+87h (411AB7h)
 {

-----------------------------------------------------------------------

JCC指条件跳转指令中,JS 若为负则跳转 jump if sign SF=1 if (i < 0);

SF标志,就是CPU对有符号数运算结果的一种记录,它记录数据的正负。在我们将数据当作有符号数
来运算的时候,可以通过它来得知结果的正负。如果我们将数据当作无符号数来运算,SF的值则没有
意义,虽然相关的指令影响了它的值。

这也就是说,CPU在执行add等指令时,是必然要影响到SF标志位的值的。至于我们需不需要这种影响,
那就看我们如何看待指令所进行的运算了。

 

1处运算完时,a的结果大于0,这是寄存器符号位SF是正的,所以在2处时即使a改为负数(debug改的只是存储器的,不是寄存器的,debug改的只是存储器的,不是寄存器的),

故会进入2的case,因为有跳转指令JS;而到3处时指令cmp又比较了因为a为-1.比较得出a这时小于0,这样debug时就进入2个if了。

 

这就是编译器的指令优化惹的祸,有问题终究还的看汇编实现啊。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值