Author Topic: postfix and prefix incrementing  (Read 6894 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 ! ! !
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

--> Donate to theSwamp<--

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:
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

--> Donate to theSwamp<--

MickD

  • Gator
  • Posts: 3314
  • (x-in)->[process]->(y-out)
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.
Forth is like the Tao: it is a Way, and is realized when followed.
Its fragility is its strength; its simplicity is its direction - Michael Ham

Lao Tzu: “To attain knowledge, add things
every day; to obtain wisdom, remove things every day.”

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 ..
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

--> Donate to theSwamp<--