首先看到以下代码
#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了。