C和汇编的__asm不起作用

5

我找到了这段代码,将堆栈指针放入EAX寄存器中(这应该是C语言中“返回”的寄存器)

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

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

我尝试使用Geany,但它不起作用了!然后我按照编译器日志的指示,更改了代码:

#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
    }
}

这次我没有与主函数的问题,但是其他函数很糟糕!!! 它无法识别__asm。 未知类型名称'mov'.... 未使用变量'eax'... 它似乎想要__asm()而不是__asm{},像正常调用函数一样。 有人可以帮我吗? PS 我有Debian 64....它可能会对64位架构有些问题?


你如何编译?阅读有关使用asm的内容。你应该使用扩展语法来传递C变量到/从汇编代码中。否则,你可能会在优化方面遇到问题。 - too honest for this site
我相信如果要让GCC识别英特尔汇编语法,你需要传递-masm=intel参数... 如果你在x86_64上编译,那可能也会有问题。我知道MSVC不支持x86_64/AMD64上的内联汇编器,可能是因为它依赖于在汇编块周围插入“粘合”代码,而这对于x86_64指令集来说太麻烦了。 - Raz0r
请注意,汇编代码必须作为一个“单一”的字符串文字给出。在传递多行时,请注意每行汇编代码的换行符。 - too honest for this site
@Raz0r:MSVC对于gcc来说是一个非常糟糕的参考(甚至对于C也是如此)。请注意,gcc有一个扩展汇编器语法来支持这种情况。 - too honest for this site
3
GCC的内嵌汇编支持与MSVC完全不同。这里有一个GCC内嵌汇编教程:https://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html。请注意,MSVC甚至不支持在x64编译中使用内嵌汇编。 - Michael Burr
显示剩余6条评论
1个回答

3

正确的GCC代码应该是:

__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;
}

根据使用情况,您可能需要使用 asm volatile,否则GCC可以在多个调用之间进行CSE。但是可能仅适用于相互内联的函数。 - Peter Cordes
1
asm的类似方法包括:获取本地地址,或使用__builtin_frame_address(0)来获取指向该函数堆栈帧中某个位置的指针。你不知道内联汇编何时运行(例如与函数序言混合在一起,然后为该函数保留空间),或其他情况,因此它可能并不是100%可靠的东西。特别是如果您不知道已经发生了多少内联。 - Peter Cordes
嗯,好的。我不确定这个用例应该是什么,但如果你只想找到最接近RSP的页面,你不需要使用noinline来取消优化。 - Peter Cordes
@PeterCordes 是的,不清楚OP在这里的意图是什么。我认为他只是想修复他的汇编代码。 - yugr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接