Help! Program crashed when call the inline assembly function continuously

Cedric Roux cedric.roux@acri-st.fr
Thu Apr 1 08:40:00 GMT 2010


spark.z wrote:
> Many thanks to you, the app works correctly according to your
> sulotion:handshake:
> 
> But I am confused with another situation as below (static int my_an = 0 ===>
> int my_an = 0)
> int main() 
> { 
>   int my_an = 0; 
>   pincrement(&my_an); 
>   pincrement(&my_an); 
>   pincrement(&my_an); 
>   printf("my_an is %d\n",my_an); 
> } 
> 
> it show me a wrong result => "my_an is 0". Is there any differences between
> the local variable and the static variable as the param? :confused:

If i write:

void pincrement(long* target)
{
    __asm__ __volatile__ ("pushq %rax");
    __asm__ __volatile__ ("lock ; incb (%%rax)" :"=m" (*target) :"a"(target), "m" (*target));
    __asm__ __volatile__ ("popq %%rax":::"rax");
}

(64b, I'm on a 64b, adapt to your needs, it's more or less the same)

some code is produced.

But it is compiled to (just the beginning):
0x0000000000400540 <main+0>:    sub    $0x18,%rsp
0x0000000000400544 <main+4>:    movq   $0xa,0x8(%rsp)
0x000000000040054d <main+13>:   push   %rax
0x000000000040054e <main+14>:   lea    0x8(%rsp),%rdx
0x0000000000400553 <main+19>:   mov    %rdx,%rax
0x0000000000400556 <main+22>:   lock incb (%rax)
0x0000000000400559 <main+25>:   pop    %rax

See what's wrong?
the first asm statement of pincrement modifies the stack pointer.
gcc doesn't know that. The second asm statement loads target by doing
"lea 0x8(%rsp), %rdx"
problem is: rsp has changed, so 0x8(%rsp) does not point anymore to target.

So one answer to your question is: add "=m" and "m" to your list of input/output
(I don't know which one is absolutely necessary, maybe both).
(And read the gcc documentation on "extended asm," it's all explained.)

But!

Your code still won't work because of the first push which modifies the stack
pointer. gcc doesn't know and on the second asm statement uses the old value.
Depending on how gcc will behave, it will work or not (it may access target
through ebp instead of esp for example, which will work).

I don't know if there is an answer to your problem. Maybe there is something to
add in the clobber list to tell the stack pointer moved, and moved of xxx bytes
in this or that direction.

Anyway, why the push/pop? gcc will know eax is modified since it's used as input
parameter in the asm statement. It will adapt itself automatically.
Or do you plan to use pincrement in another context where you absolutely
need eax not to change inside of pincrement? (in which case, maybe it's
better to write it directly in assembly).



More information about the Gcc-help mailing list