-
2008年03月22日
++i和i--
分类:工具:Visual C++ 9.0(2008)/Turbo C+IDA Pro
平台:WinXP SP2
代码:
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
int i=8;
printf("%d,%d,%d,%d,%d",++i,--i,i--,i++,-i--);
cout<<++i<<","<<--i<<","<<i--<<","<<i++<<","<<-i--<<endl;
}
注:灰色代码为C++调用,两者输出结果一致。
Debug输出为7,7,8,7,-8,用IDA Pro 5.2反汇编看到
_wmain proc near
var_D8= dword ptr -0D8h
var_D4= dword ptr -0D4h
var_D0= dword ptr -0D0h
var_8= dword ptr -8
push ebp
mov ebp, esp
sub esp, 0D8h
push ebx
push esi
push edi
lea edi, [ebp+var_D8]
mov ecx, 36h
mov eax, 0CCCCCCCCh
rep stosd
mov [ebp+var_8], 8 ;将8赋值给i
mov eax, [ebp+var_8] ;将i存进eax寄存器
neg eax ;求补,eax值变为-i即-8
mov [ebp+var_D0], eax ; [ebp+var_D0] 即第5个参数值为-8
mov ecx, [ebp+var_8] ;将i存进ecx寄存器
sub ecx, 1 ;ecx减1即7
mov [ebp+var_8], ecx ;i=i--即7
mov edx, [ebp+var_8] ;将i存进edx寄存器
mov [ebp+var_D4], edx ;[ebp+var_D4] 即第4个参数值为7
mov eax, [ebp+var_8] ;再次将i存进eax寄存器
add eax, 1 ;eax加1即8
mov [ebp+var_8], eax ;i=i++即8
mov ecx, [ebp+var_8] ;再次将i存进ecx寄存器
mov [ebp+var_D8], ecx ; [ebp+var_D8] 即第3个参数值为8
mov edx, [ebp+var_8] ;再次将i存进edx寄存器
sub edx, 1 ;edx-1即7
mov [ebp+var_8], edx ;i=i--即7
mov eax, [ebp+var_8] ;再次将i存进eax寄存器
sub eax, 1 ;eax减1即6
mov [ebp+var_8], eax ;i=--i即6
mov ecx, [ebp+var_8] ;再次将i存进ecx寄存器
add ecx, 1 ;ecx加1即7
mov [ebp+var_8], ecx ;i=++i即7
mov esi, esp
mov edx, [ebp+var_D0] ;5个参数从右至左开始入栈
push edx
mov eax, [ebp+var_D4]
push eax
mov ecx, [ebp+var_D8]
push ecx
mov edx, [ebp+var_8]
push edx
mov eax, [ebp+var_8]
push eax
push offset aDDDDD ; "%d,%d,%d,%d,%d"
call ds:__imp__printf
add esp, 18h
cmp esi, esp
call j___RTC_CheckEsp
xor eax, eax
pop edi
pop esi
pop ebx
add esp, 0D8h
cmp ebp, esp
call j___RTC_CheckEsp
mov esp, ebp
pop ebp
retn
_wmain endp
Release输出为 8,8,8,8,-8。
_main proc near ;编译器在编译过程中直接优化然后输出结果
push 0FFFFFFF8h ;-i
push 8
push 8
push 8
push 8
push offset aDDDDD ; "%d,%d,%d,%d,%d"
call ds:__imp__printf
add esp, 18h
xor eax, eax
retn
_main endp
Borland Turbo C v2.01输出结果为7,6,8,7,-8。
_main proc near
argc= word ptr 4
argv= dword ptr 6
envp= dword ptr 0Ah
push bp
mov bp, sp
push si
mov si, 8 ;将8赋值给i
mov ax, si ;将i存进ax
dec si ;i=i—即7
neg ax ;求补,ax值为-i即-8
push ax ;第5个参数入栈值为-8
mov ax, si ;再次将i存进ax
inc si ;i=i++即8
push ax ;第4个参数入栈值为7
mov ax, si ;再次将i存进ax
dec si ;i=i—即7
push ax ;第3个参数入栈值为8
dec si ;i=--i即6
mov ax, si ;再次将i存进ax
push ax ;第2个参数入栈值为6
inc si ;i=++i即7
mov ax, si ;再次将i存进ax
push ax ;第1个参数入栈值为7
mov ax, 194h
push ax ; format
call _printf
add sp, 0Ch
pop si
pop bp
retn
_main endp
从上面的结果可以看出,虽然参数均是从右至左入栈,但每个编译器对运算符处理策略的不同,导致了结果的不确定。因此它不适合出现在程序中,当然更不适合用作笔试/面试题了。
上面的结果同样也瞥现一般++i比i++效率更高的原因。
【资源】
Intel® 64 and IA-32 Architectures Software Developer's Manuals、Volume 2A: Instruction Set Reference, A-M、Volume 2B: Instruction Set Reference, N-Z
ECMA C# and Common Language Infrastructure Standards
随机文章:
影音传送带暴破 2009年10月19日VbsEdit暴破 2009年10月12日分享几本WinDBG相关电子书 2009年07月27日自动分析Minidump文件 2009年06月19日Debug文章聚合 2009年06月10日
收藏到:Del.icio.us

评论
而且,那条printf,语义上就是错误的……像是在做RE