GCC inline - push address, not its value to stack

user4520

I'm experimenting with GCC's inline assembler (I use MinGW, my OS is Win7). Right now I'm only getting some basic C stdlib functions to work. I'm generally familiar with the Intel syntax, but new to AT&T.

The following code works nice:

char localmsg[] = "my local message";
asm("leal %0, %%eax" : "=m" (localmsg));
asm("push %eax");
asm("call %0" : : "m" (puts));
asm("add $4,%esp");

That LEA seems redundant, however, as I can just push the value straight onto the stack. Well, due to what I believe is an AT&T peculiarity, doing this:

asm("push %0" : "=m" (localmsg));

will generate the following assembly code in the final executable:

PUSH DWORD PTR SS:[ESP+1F]

So instead of pushing the address to my string, its contents were pushed because the "pointer" was "dereferenced", in C terms. This obviously leads to a crash.

I believe this is just GAS's normal behavior, but I was unable to find any information on how to overcome this. I'd appreciate any help.

P.S. I know this is a trivial question to those who are experienced in the matter. I expect to be downvoted, but I've just spent 45 minutes looking for a solution and found nothing.

P.P.S. I realize the proper way to do this would be to call puts( ) in the C code. This is for purely educational/experimental reasons.

David Wohlferd

While inline asm is always a bit tricky, calling functions from it is particularly challenging. Not something I would suggest for a "getting to known inline asm" project. If you haven't already, I suggest looking through the very latest inline asm docs. A lot of work has been done to try to explain how inline asm works.

That said, here are some thoughts:

1) Using multiple asm statements like this is a bad idea. As the docs say: Do not expect a sequence of asm statements to remain perfectly consecutive after compilation. If certain instructions need to remain consecutive in the output, put them in a single multi-instruction asm statement.

2) Directly modifying registers (like you are doing with eax) without letting gcc know you are doing so is also a bad idea. You should either use register constraints (so gcc can pick its own registers) or clobbers to let gcc know you are stomping on them.

3) When a function (like puts) is called, while some registers must have their values restored before returning, some registers can be treated as scratch registers by the called function (ie modified and not restored before returning). As I mentioned in #2, having your asm modify registers without informing gcc is a very bad idea. If you know the ABI for the function you are calling, you can add its scratch registers to the asm's clobber list.

4) While in this specific example you are using a constant string, as a general rule, when passing asm pointers to strings, structs, arrays, etc, you are likely to need the "memory" clobber to ensure that any pending writes to memory are performed before starting to execute your asm.

5) Actually, the lea is doing something very important. The value of esp is not known at compile time, so it's not like you can perform push $12345. Someone needs to compute (esp + the offset of localmsg) before it can be pushed on the stack. Also, see second example below.

6) If you prefer intel format (and what right-thinking person wouldn't?), you can use -masm=intel.

Given all this, my first cut at this code looks like this. Note that this does NOT clobber puts' scratch registers. That's left as an exercise...

#include <stdio.h>

int main()
{
  const char localmsg[] = "my local message";

  int result;

  /* Use 'volatile' since 'result' is usually not going to get used,
     which might tempt gcc to discard this asm statement as unneeded. */

  asm volatile ("push %[msg] \n\t"   /* Push the address of the string. */
                "call %[puts] \n \t" /* Call the print function. */
                "add $4,%%esp"       /* Clean up the stack. */

                : "=a" (result) /* The result code from puts. */
                : [puts] "m" (puts), [msg] "r" (localmsg)
                : "memory", "esp");

   printf("%d\n", result);
}

True this doesn't avoid the lea due to #5. However, if that's really important, try this:

#include <stdio.h>
const char localmsg[] = "my local message";

int main()
{

  int result;

  /* Use 'volatile' since 'result' is usually not going to get used. */

  asm volatile ("push %[msg] \n\t" /* Push the address of the string. */
                "call %[puts] \n \t" /* Call the print function. */
                "add $4,%%esp"       /* Clean up the stack. */

                : "=a" (result) /* The result code. */
                : [puts] "m" (puts), [msg] "i" (localmsg)
                : "memory", "esp");

   printf("%d\n", result);
}

As a global, the address of localmsg is now knowable at compile time (ok, I'm simplifying a bit), the asm produced looks like this:

push $__ZL8localmsg
call _puts
add $4,%esp

Tada.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

GCC inline - push address, not its value to stack

From Dev

Branch to an address using GCC inline ARM asm

From Dev

Meaningful stack traces for address sanitizer in GCC

From Dev

How does gcc push local variables on to the stack?

From Dev

Writing to address based on its value

From Dev

Gcc inline ASM, set EBX to char array address using LEA

From Dev

Replace "inline style" with a "css class" depending by value of its inline style

From Dev

C - GCC generates wrong instructions when returning local stack address

From Dev

Can I create a Thread with its stack at a specific address?

From Dev

Generic stack don't push or pop value

From Dev

push(int[][]) in a stack is duplicating the same value Java

From Dev

Assigning an int's own address to its value

From Dev

Loading a value from an array without its address

From Dev

Push in a Stack char-value have different value

From Dev

Push in a Stack char-value have different value

From Dev

Find a keyword "id" and change its value in inline style

From Dev

Checking a checkbox must hold the text value of its inline div

From Dev

Find a keyword "id" and change its value in inline style

From Dev

How do I tell gcc that my inline assembly clobbers part of the stack?

From Dev

How to push url onto value stack in Struts 2

From Dev

variable value and its address using pointers in C++

From Dev

Initialising an integer pointer with a value at its pointee's address there itself

From Dev

Why ARM gcc push register r3 and lr into stack at the beginning of a function?

From Dev

x86 - Does CALL instruction ALWAYS push the address pointed by EIP to stack?

From Dev

postfix notation - Stack pop and push help, memory address printed instead of actual numbers

From Java

Git warning: push.default is unset; its implicit value is changing

From Dev

Both observableArray itself and its inner value have push methods

From Dev

Error with gcc inline assembly

From Dev

gcc denying inline request

Related Related

  1. 1

    GCC inline - push address, not its value to stack

  2. 2

    Branch to an address using GCC inline ARM asm

  3. 3

    Meaningful stack traces for address sanitizer in GCC

  4. 4

    How does gcc push local variables on to the stack?

  5. 5

    Writing to address based on its value

  6. 6

    Gcc inline ASM, set EBX to char array address using LEA

  7. 7

    Replace "inline style" with a "css class" depending by value of its inline style

  8. 8

    C - GCC generates wrong instructions when returning local stack address

  9. 9

    Can I create a Thread with its stack at a specific address?

  10. 10

    Generic stack don't push or pop value

  11. 11

    push(int[][]) in a stack is duplicating the same value Java

  12. 12

    Assigning an int's own address to its value

  13. 13

    Loading a value from an array without its address

  14. 14

    Push in a Stack char-value have different value

  15. 15

    Push in a Stack char-value have different value

  16. 16

    Find a keyword "id" and change its value in inline style

  17. 17

    Checking a checkbox must hold the text value of its inline div

  18. 18

    Find a keyword "id" and change its value in inline style

  19. 19

    How do I tell gcc that my inline assembly clobbers part of the stack?

  20. 20

    How to push url onto value stack in Struts 2

  21. 21

    variable value and its address using pointers in C++

  22. 22

    Initialising an integer pointer with a value at its pointee's address there itself

  23. 23

    Why ARM gcc push register r3 and lr into stack at the beginning of a function?

  24. 24

    x86 - Does CALL instruction ALWAYS push the address pointed by EIP to stack?

  25. 25

    postfix notation - Stack pop and push help, memory address printed instead of actual numbers

  26. 26

    Git warning: push.default is unset; its implicit value is changing

  27. 27

    Both observableArray itself and its inner value have push methods

  28. 28

    Error with gcc inline assembly

  29. 29

    gcc denying inline request

HotTag

Archive