5

I found this piece of code to put the stack pointer into EAX register(It should be the register used by "return" in C)

#include <stdio.h>
unsigned long get_sp(){
    unsigned long stp;
    __asm{
        mov
        eax, esp
        }
}

void main(void){
printf("\n0x%x", get_sp());
}

I tried it with Geany but it doesn't works!! Then I follow the compiler log and I changed the code in this way:

#include <stdio.h>

unsigned long get_sp(void);

int main(void){
printf("\n0x%ld", get_sp());
return 0;
}


unsigned long get_sp(void){
    unsigned long stp;
    __asm{
        mov eax, esp
    }
}

this time I have no problems with the main but the other function is a tragedy!!! It doesn't recognize __asm. unknown type name 'mov'.... unused variable 'eax'... It seems like it wants __asm() instead of __asm{}, like a normal call of a function. Somebody can help me? PS I have debian 64....it can have some problems with the 64 architecture??

nicanz
  • 347
  • 1
  • 2
  • 11
  • How do you compile? Read about using [`asm`](https://gcc.gnu.org/onlinedocs/gcc-4.9.2/gcc/Extended-Asm.html#Extended-Asm). You should use the extended syntax to pass C variables to/from your assembler code. Otherwise you might get problems with optimizations. – too honest for this site Jun 18 '15 at 00:31
  • I believe for GCC to recognise intel assembly syntax, you'll have to pass -masm=intel ... If you're compiling on x86_64 that could also be a problem. I know MSVC does not support inline assembler on x86_64/AMD64, probably because it relied on inserting "glue" code around the assembly blocks and that was too troublesome for x86_64 instruction set – Raz0r Jun 18 '15 at 00:32
  • Note that the assembler code has to be given as a _single_ string literal. Mind the newline for each line of the assembler code when passing multiple lines. – too honest for this site Jun 18 '15 at 00:37
  • @Raz0r: MSVC is a very bad reference for gcc (well, it even is for C). Note that gcc has an extended assembler syntax to support such cases. – too honest for this site Jun 18 '15 at 00:38
  • 3
    GCC's inline assembly support is completely different than MSVC's. There is a GCC inline assembly tutorial here: https://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html. Note that MSVC doesn't even support inline assembly in x64 builds. – Michael Burr Jun 18 '15 at 00:46
  • thanks @MichaelBurr!! I didn't know the "AT&T code" for gcc....I studied assembly long time ago and now I want to restart with it...but honestly, I don't remember very much!! I understood that I have to use ' __asm__ ("movl %eax, %esp");' and the "Compilation finished successfully" but I have a "Segmentation fault" maybe because eax and esp are 32 registers....I found [this](http://stackoverflow.com/questions/1753602/registers-for-x86-64-processors) and I tried with rax and rsp but **Error: incorrect register '%rsp' used with 'l' suffix** – nicanz Jun 18 '15 at 01:59
  • In the AT&T syntax the `l` suffix on an instruction means that the operands are 32-bit 'longs'. Use the `q` suffix to signify 64-bit 'quadwords'. Also remember that in AT&T syntax the operand order is source followed by destination - the opposite of Intel syntax. So `movq %rsp,%rax` is what I think you want. Also, you can specify that Intel syntax should be used with the `-masm=intel` command line option. – Michael Burr Jun 18 '15 at 04:28
  • ok ok..thanks again @MichaelBurr (for understanding and assistance).I'm not very good with english and I still have some difficulty to read a long english text! Now I understand a little bit more what Raz0r meant with `-masm=intel` but I still have to figure out how it works :) – nicanz Jun 18 '15 at 15:05
  • I'm happy to found a your comment in a six years old [post](http://stackoverflow.com/questions/199966/how-do-you-use-gcc-to-generate-assembly-code-in-intel-syntax). But it is to translate a C file into an assembly with `gcc -S file.c` or `gcc -S -masm=intel file.c`. Is this what you try to tell me or I misunderstood? – nicanz Jun 18 '15 at 15:27
  • The `-S` option tells gcc to produce the assembly output files. The `-masm=intel` option tells gcc to format the assembly in Intel format. I think that it also tells gcc to process any inline assembly as Intel formatted code. – Michael Burr Jun 18 '15 at 16:18
  • very helpful, you gave me the right direction...I hope I can walk it on my legs now....thanks for all! – nicanz Jun 18 '15 at 17:21

1 Answers1

3

The correct GCC code would be

__attribute__((noinline,noclone))
unsigned long get_sp(void) {
  unsigned long stp;
  asm(
    // For x86_64: "movq %%rsp, %0"
    "movl %%esp, %0"
    : "=r"(stp)
  );
  return stp;
}
yugr
  • 19,769
  • 3
  • 51
  • 96
  • Depending on the use-case, you might want `asm volatile` or else GCC can CSE that across multiple calls. But probably only within functions which inline into each other anyway. – Peter Cordes Jun 26 '19 at 15:40
  • 1
    Non-`asm` ways to do something similar include: take the address of a local, or use [`__builtin_frame_address(0)`](https://gcc.gnu.org/onlinedocs/gcc/Return-Address.html) to get a pointer to somewhere in this function's stack frame. You don't know when that inline asm will run (e.g. mixed in with the function prologue before reserving space for this function), or whatever, so it's maybe not a 100% reliable thing anyway. Especially if you don't know how much inlining has happened. – Peter Cordes Jun 26 '19 at 15:42
  • Uh, ok. I'm not sure what the use-case of this is supposed to be, but if you just want to find out to the nearest page where RSP is, you don't need to deoptimize by using noinline. – Peter Cordes Jun 26 '19 at 18:50
  • @PeterCordes Yes, it's not clear what was the OP's intent here. I asssumed he just wanted to fix his asm. – yugr Jun 27 '19 at 01:33