Not logged in, Join Here! or Log In Below:  
 
News Articles Search    
 

 Home / General Programming / Stupid compiler question Account Manager
 
Archive Notice: This thread is old and no longer active. It is here for reference purposes. This thread was created on an older version of the flipcode forums, before the site closed in 2005. Please keep that in mind as you view this thread, as many of the topics and opinions may be outdated.
 
Steven Hansen

May 03, 2005, 01:22 PM

Background: The __fastcall declaration in C++ specifies that arguments should be passed in registers if possible. The __declspec(naked) declaration removes the preservation of register code that typically is associated with function calls.

So, if I use both of these in tandem, is the compiler smart enough to prepare for and recover from using this type of function?

Take an example I found on the forum:

  1.  
  2. __declspec(naked) unsigned __fastcall floorPowerOf2(unsigned x) {
  3.     __asm {
  4.         xor eax,eax
  5.         bsr ecx,ecx
  6.         setnz al
  7.         shl eax,cl
  8.         ret
  9.     }
  10. }
  11.  


Well, this function overwrites eax and ecx, and doesn't store/restore previous values. Does the compiler take this into account correctly? Say we had:
  1.  
  2. void dumbfunction() {
  3.    for (int index = 0; index < 155; index++) {
  4.       int var = floorPowerOf2(index);
  5.    }
  6. }
  7.  

If ecx is used as the loop counter by the compiler, with floorPowerOf2 called in the loop, does it trounce the counter, or did the compiler save it somewhere before the call (155 correct iterations)?

On the other hand, I wrote the above program out (approximately) and examined the assembly output. The compiler seems to read from memory each time it accesses index, and writes it out to memory each time the value of index changes. No variable value seems to be stored in memory for very long apparently. That seems sub-optimal, but safe. Is this approach a general compiler practice? Then again, my program was very small, and not optimized (debug mode).

Any insights are appreciated.

 
Patrick Grawehr

May 03, 2005, 03:07 PM

You cannot make any conclusions about how "smart" the compiler behaves if you're running in debug mode. One of the effects of the debug mode IS that all optimizations are disabled. The compiler doesn't use the registers for optimization either. It will even re-assign the same value to the same register twice in a row if the value is used multiple times. This ensures that all operations are executed exactly in the order they appear in the source code, which makes debugging a lot easier. (Have you ever tried to debug release mode code in assembly mode? You will not rerecognize your code).
So to answer your question, you should definitelly look at the optimized compiler output. ASFAIK, if you use declspec(naked), you must be aware yourself that the calling conventions (caller vs callee saved registers) is kept intact.

 
Nick

May 03, 2005, 03:26 PM

eax, ecx and edx are always free to be used by any function. eax is the return value register, also when the funcion doesn't return anything, and ecx and edx are scratch registers.

__declspec(naked) just means the compiler does not set up a stack frame for you.

 
Steven Hansen

May 03, 2005, 03:52 PM

Thanks.

 
Alex Herz

May 04, 2005, 01:43 AM

I wonder if there is any guaranty in which register the x from the sample function will end up.
The doc says that the compiler will "try" to put it into ecx. But in release mode anything can happen..I guess???

Wouldn't it make more sense to activate full optimization and to framepointer omitting? The comiler would probably inline the function and ommit the frame pointer anyways in full release...and it would be more portable...

Alex

 
This thread contains 5 messages.
 
 
Hosting by Solid Eight Studios, maker of PhotoTangler Collage Maker.