Author Topic: postfix and prefix incrementing  (Read 13808 times)

0 Members and 1 Guest are viewing this topic.

Chuck Gabriel

  • Guest
Re: postfix and prefix incrementing
« Reply #15 on: February 05, 2006, 09:39:11 PM »
Here is something to think about (please ignore the fact that this appears to contradict my previous statements :D).  MSVC++6 "compiled" the following C source code:

Code: [Select]
int main() {
int i = 0;
int retVal;
retVal = ++i;
retVal = i++;
return 0;
}

into this assembler code with all optimizations turned off.  The source code is shown inline prior to its assembly equivalent.

Code: [Select]
TITLE C:\My Documents\Programming\Projects\C++\Experiments\increment\main.cpp
.386P
include listing.inc
if @Version gt 510
.model FLAT
else
_TEXT SEGMENT PARA USE32 PUBLIC 'CODE'
_TEXT ENDS
_DATA SEGMENT DWORD USE32 PUBLIC 'DATA'
_DATA ENDS
CONST SEGMENT DWORD USE32 PUBLIC 'CONST'
CONST ENDS
_BSS SEGMENT DWORD USE32 PUBLIC 'BSS'
_BSS ENDS
_TLS SEGMENT DWORD USE32 PUBLIC 'TLS'
_TLS ENDS
FLAT GROUP _DATA, CONST, _BSS
ASSUME CS: FLAT, DS: FLAT, SS: FLAT
endif
PUBLIC _main
_TEXT SEGMENT
_i$ = -4
_retVal$ = -8
_main PROC NEAR

; 1    : int main() {

push ebp
mov ebp, esp
sub esp, 8

; 2    : int i = 0;

mov DWORD PTR _i$[ebp], 0

; 3    : int retVal;
; 4    : retVal = ++i;

mov eax, DWORD PTR _i$[ebp]
add eax, 1
mov DWORD PTR _i$[ebp], eax
mov ecx, DWORD PTR _i$[ebp]
mov DWORD PTR _retVal$[ebp], ecx

; 5    : retVal = i++;

mov edx, DWORD PTR _i$[ebp]
mov DWORD PTR _retVal$[ebp], edx
mov eax, DWORD PTR _i$[ebp]
add eax, 1
mov DWORD PTR _i$[ebp], eax

; 6    : return 0;

xor eax, eax

; 7    : }

mov esp, ebp
pop ebp
ret 0
_main ENDP
_TEXT ENDS
END

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: postfix and prefix incrementing
« Reply #16 on: February 05, 2006, 09:56:53 PM »

BabelFish spat the dummy on the translation Chuck :-) ...  help ! ! !
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Chuck Gabriel

  • Guest
Re: postfix and prefix incrementing
« Reply #17 on: February 05, 2006, 10:00:56 PM »
The only part worth understanding is the fact that i++ and ++i both took four mov instructions and one add instruction.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: postfix and prefix incrementing
« Reply #18 on: February 05, 2006, 10:07:48 PM »
ta !   :lol:
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

MickD

  • King Gator
  • Posts: 3619
  • (x-in)->[process]->(y-out) ... simples!
Re: postfix and prefix incrementing
« Reply #19 on: February 05, 2006, 10:16:23 PM »
Bablefish modified code :D
Code: [Select]
_i$ = -4            ;4 bytes into the stack = start address for 1 double word variable
_retVal$ = -8       ;8 bytes into the stack = start address for another dword variable
_main PROC NEAR     ;address of main procedure


; 1    : int main() {

push ebp                          ;preserve the ebp register
mov ebp, esp                      ;move the stack pointer into ebp
sub esp, 8                        ;subtract 8 bytes from the stack pointer
                                  ;(move 2 dwords (64bits) into the stack)
                                  ;to allow for our variables _i$ and _retVal$

; 2    : int i = 0;

mov DWORD PTR _i$[ebp], 0         ;move 0 into address in ebp (_i$,this is the start of the stack!)

; 3    : int retVal;         
; 4    : retVal = ++i;

mov eax, DWORD PTR _i$[ebp]          ;move what's in _i$ into eax
add eax, 1                           ;add 1 to it (increment) eax, result in eax (0+1=1)
mov DWORD PTR _i$[ebp], eax          ;move result back into _i$(ebp)
mov ecx, DWORD PTR _i$[ebp]          ;move _i$ into ecx (ecx = 1)
mov DWORD PTR _retVal$[ebp], ecx     ;move ecx into _retVal

; 5    : retVal = i++;

mov edx, DWORD PTR _i$[ebp]         ;move _i$ into edx
mov DWORD PTR _retVal$[ebp], edx    ;move edx into _retVal$
mov eax, DWORD PTR _i$[ebp]         ;move _i$ into eax
add eax, 1                          ;add 1 to eax, eax = 2, we haven't emptied eax!
mov DWORD PTR _i$[ebp], eax         ;move result back into _i$

; 6    : return 0;

xor eax, eax        ;set all bits to zero in eax to clear it.

; 7    : }

mov esp, ebp        ;move the top of the stack back into stack pointer
                    ;register to balance the stack (like poping twice)
pop ebp             ;restore the ebp register
ret 0
_main ENDP
_TEXT ENDS
END   

As Chuck said, it's the same instruction count but notice we didn't do any 'pop'ing, we just get the stack pointer (address of stack for arguments sake) and index into and out of the stack using the addresses of the variable calculated by the size of the variables and the stack address.
I'd guess that MSIL does it this way as IL is a 'pseudo' assembler, ie it has to be parsed and compiled into 'proper' assembler/machine instructions before use. Therefore it can create it's own 'compile time' stacks etc.
"Short cuts make long delays,' argued Pippin.”
J.R.R. Tolkien

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: postfix and prefix incrementing
« Reply #20 on: February 05, 2006, 10:27:17 PM »
ta !   :lol:

..and ditto to Mick .

If I recall, Jon Skeet or Jess Liberty suggested using postfix by default, just for consistancy, unless  prefix was Explicitly needed.

The options could always be benchmarked I s'pose, but I can't see that it would be a really critical issue considering the IL is 'compiled' after Jitting anyway.

Interesting discussion ..
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.