Page 1 of 1
disable optimization per-function with gcc [SOLVED]
Posted: Sun Jan 20, 2008 4:37 pm
by pini
Here is my problem:
I have assembly code that pushes arguments and calls a C function.
The C function looks like :
Code: Select all
void f(int arg) {
print("some message");
}
This is compiled with -O2 and gcc seems to use the fact that the argument is not used. In fact, it stores the argument to print (the string) at the place where arg is, and so everything is broken upon f return.
This doesn't happen when compiling with -O0, so I'd like to know if there's a way to tell gcc not to optimize anything related to arg (including assuming its stack space is free) ?
Posted: Sun Jan 20, 2008 5:34 pm
by phire
I'm not completely sure, but try declearing arg volatile.
Posted: Sun Jan 20, 2008 9:20 pm
by proxy
The problem is not with optimizations, but that with standard C calling convention the caller cleans up the params it pushed onto the stack. One thing you should do is do what linux does for it's "asmlinkage" macro which is an attribute which guarantees C style calling convention.
Posted: Mon Jan 21, 2008 4:29 am
by pini
phire: I already tried with volatile but didn't help.
proxy: I'll give a try to the __attribute__((regparm(0))) (macro "asmlinkage") this evening
Re: disable optimization per-function with gcc
Posted: Mon Jan 21, 2008 4:48 am
by jal
pini wrote:This is compiled with -O2 and gcc seems to use the fact that the argument is not used. In fact, it stores the argument to print (the string) at the place where arg is, and so everything is broken upon f return.
I really don't see how 'everything' could be 'broken upon return'. Upon return, the stack location used to store arg should be released anyway. It is temporary. GCC using the location for something else is just the same as you adding a line saying 'arg = (int)(int *)"some message"'. Are you sure there's not something else that's screwed up?
JAL
Posted: Mon Jan 21, 2008 6:38 am
by pini
It would be the case in the general way, but my calling code is for interrupt handling and looks like this :
Code: Select all
; some stuff
push ds ; save
call my_c_function
pop ds ; restore
; some stuff
As you can see, the argument is not thrown away, as it would normally be the case but reused and that's why I want gcc not to touch it.
Posted: Mon Jan 21, 2008 8:05 am
by jal
pini wrote:As you can see, the argument is not thrown away, as it would normally be the case but reused and that's why I want gcc not to touch it.
You're skating on really thin ice here, as gcc may change any registers in a C function as it sees fit, and may change anything on the stack frame passed to it as it sees fit. You are calling a C-function, but do not adhere to the calling convention for that function.
JAL
Posted: Tue Jan 22, 2008 7:42 am
by pini
Actually, I change my assembly code to fit the calling convention :
Code: Select all
; some stuff
push ds
push esp
call my_c_func
add esp,4
pop ds
And changed the prototype of the C function do take a int* rather than an int.
Everything works perfectly now.
Posted: Tue Jan 22, 2008 10:48 am
by Combuster
I'd simply have used something like
Posted: Tue Jan 22, 2008 11:58 am
by pini
Well, I still need the pushed value of ds after the call, so I'll stick with my current hack.
Posted: Tue Jan 22, 2008 12:10 pm
by proxy
is your function supposed to alter the value of ds? If not, then this would do as well (what you currently have will have the net effect of pass-by-reference since you pop the result back into ds).
So the simpler code could be this:
Code: Select all
; some stuff
push ds
push esp
call my_c_func
add esp,8
note that the size pushed on the stack is 32-bit when pushing ds, so when you what to undo it, you need to pop 4 bytes.
proxy[/code]