0

consider the following function that won't get inlined and assume x86 as platform:

void doSomething(int & in){
//do something
}

firstly I'm not sure such scenario would happen but since I think it is possible I'm gonna ask so IF whenever in any caller this function is called the argument to be supplied lies exactly at the top of the caller stack frame so that in the called function access to that through ebp register(after callee has moved content of esp into ebp) in assembly language is possible do you suggest we ignore declaring a parameter at all for function and use assembly to access our arguments in this exceptional case or just leave function definition as it was and leave it to compiler to do what it does? since I haven't read anywhere that compiler would consider such exceptional case as a factor for calling convention and I think it'll simply generate code to pass a pointer to the argument to the callee stack frame or one of registers

Pooria
  • 2,017
  • 1
  • 19
  • 37
  • 3
    Why would you want to do that? You would have to have very strong reasons to do something so crazy. – juanchopanza Jul 05 '13 at 07:36
  • Mixing C++ with assembly is like mixing ultra-high octane gasoline with crude oil. – Mark Garcia Jul 05 '13 at 07:39
  • By the way, how would you know the function won't get inlined? Unless you use [specific keywords](http://stackoverflow.com/questions/3329214/is-it-possible-to-force-a-function-not-to-be-inlined) of a particular compiler, it is up to the compiler to do whatever he wants. The keyword `inline` is just merely an indication that you would like the compiler to inline it. – Boris Dalstein Jul 05 '13 at 07:41
  • The answers you've got so far should suggest to you that you are trying to do something flat-out wrong. So a couple of questions to clear up what you are trying to achieve might be in order. Why do you consider this "exceptional"? Passing a reference to an integer seems a reasonably normal thing to do. You've flagged this "optimization" - have you profiled the code to identify the c++ version of this method as a performance bottleneck? If you have, it's much more likely that your algorithm is a bad fit for the problem than that the implementation is too slow. – Nigel Hawkins Jul 05 '13 at 08:19

3 Answers3

4

First of all, it's SO easy for this to break - for example, you get a different version of compiler, that generates code differently. Or you change optimisation features. Never mind the situation where you suddenly need to use doSomething in a different place and then it won't work, because the variable is no longer on the top of the stack.

Second, assuming that the code inside the function is short enough, it's highly likely that the compiler will inline the function, so you don't "lose" anything at all.

Third, a single argument in modern compilers, is typically passed in a register anyway, so there is no benefit in this when optimisation is enabled.

If you really think there is worthwhile benefit in this, and the compiler won't inline or otherwise optimise the code [have you looked at the generated code?], then try using forceinline or always_inline or whatever it is called in your compiler (most compilers have such an option). If that doesn't work, use a macro to inline it by hand. Or simply move the code to where it is called by "copy-n-paste".

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
2

Your note "the argument to be supplied lies exactly at the top of the caller stack frame so that in the called function access to that through ebp register" contains a factual misunderstanding.

That's because of the following things:

  • you're assuming a stack-based calling convention, i.e. function arguments being pushed to the stack by the caller before calling the function. That's not generally the case; even on 32bit x86, there's non-stack-based calling conventions (for example, Windows fastcall or the GNU GCC ones used in the 32bit linux kernel). If such are used, the argument wouldn't be found on top of the stack, but rather in ... whatever register is used to hold the first argument.


    But even if you have stack-based parameter passing ... still:

  • you've missed that on x86 at the very least the call instruction is pushing a return address onto the top of the stack, so that when the first instruction of a function reached that way is executing, ESP will not point to the first arg of that function, but to the return address.
  • you've missed that EBP is a callee-saved (preserved over function calls) registers, and not initialized on your behalf by the architecture - it's necessary for the generated code to explicitly set it up. A function which wants to use it (even if only as a framepointer) is therefore obliged to save it somewhere before using it. That means the normal prologue will have push EBP; mov EBP, ESP (you cannot only do MOV EBP, ESP because that would overwrite the caller's EBP which is invalid / which you may not do). Therefore, if you like to refer to the first argument of the function, you'd need [ EBP + 8 ] not [ EBP ].
    If you're not using framepointers, then the first argument (due to the call which was used to reach the function having pushed a return address) is at [ ESP + 4 ] not [ ESP ].

I hope this clarifies a little.

I agree with the other posters that clarifying the question would help, what exactly you want to achieve and why you think assembly language might be useful here.

FrankH.
  • 17,675
  • 3
  • 44
  • 63
1

No, I would not. Calling conventions may vary (between x86 and x86_64); Parameters could be pushed to the stack or put into register, and I'm not sure you can know for sure where they'll be.

Writing this in assembly, unless you really know what you're doing is likely to lead to undefined behavior code.

Xaqq
  • 4,308
  • 2
  • 25
  • 38