Assembly 使用写入系统调用程序集打印寄存器值

Assembly 使用写入系统调用程序集打印寄存器值,assembly,stack-overflow,inline-assembly,Assembly,Stack Overflow,Inline Assembly,实际上,我想使用WRITE系统调用打印当前ESP值,因为我将在我的C程序中将其用作内联程序集。此GNU C/C++代码(GNU,因为它用于检索当前堆栈指针值的内联程序集的样式)将打印堆栈指针的当前值(十六进制) 由于static\uuuuuu inline\uuuuu,gcc在大多数情况下(除非使用函数指针)实际上不会创建此函数,而是直接将代码嵌入调用站点 您可以构建一个更精细的作品,它可以做如下操作: static __inline__ void printESP(void) { st

实际上,我想使用WRITE系统调用打印当前ESP值,因为我将在我的C程序中将其用作内联程序集。

此GNU C/C++代码(GNU,因为它用于检索当前堆栈指针值的内联程序集的样式)将打印堆栈指针的当前值(十六进制)

由于
static\uuuuuu inline\uuuuu
,gcc在大多数情况下(除非使用函数指针)实际上不会创建此函数,而是直接将代码嵌入调用站点

您可以构建一个更精细的作品,它可以做如下操作:

static __inline__ void printESP(void) {
    static const hexdigit[] = "0123456789ABCDEF\n";
    uintptr_t SP;

    __asm__ __volatile__("mov %%esp, %0\n\t" : "=r"(SP));

    write(1, &hexdigit[SP >> 28], 1);
    write(1, &hexdigit[0xf & SP >> 24], 1);
    write(1, &hexdigit[0xf & SP >> 20], 1);
    write(1, &hexdigit[0xf & SP >> 16], 1);
    write(1, &hexdigit[0xf & SP >> 12], 1);
    write(1, &hexdigit[0xf & SP >> 8], 1);
    write(1, &hexdigit[0xf & SP >> 4], 1);
    write(1, &hexdigit[0xf & SP], 1);
    write(1, &hexdigit[16], 1);
}
这将在堆栈上构造一个临时缓冲区,并只调用一次
write()

第二段代码的缺点是它实际上占用了stackspace,这意味着如果调用它,比如说,从一个溢出堆栈和/或损坏stackpointer的函数调用它,它将崩溃。一个字符接一个字符地发送地址的第一个简单的方法可能仍然有效

注意您的初始汇编代码:它使用全局缓冲区,因此不是线程安全的;如果您同时从多个线程调用它,它们将损坏变量,您将得到垃圾。所以不,我不会帮助“修复”那个

该方法的一般说明:就个人而言,我认为这就是调试器的用途。这种特定类型的运行时插装(以这种方式-直接打印值)非常不有用;如果是运行时检测,那么最好登录到内存跟踪缓冲区,在那里可以记录扩展信息,如(部分)堆栈跟踪、线程ID、时间戳、其他寄存器值等,以及堆栈指针。使用内存中(环形)缓冲区不依赖于filedescriptor 1的特殊含义,并且允许“上下文”信息比stackpointer值更能描述正在发生的事情


此外,如果该值不必100%精确,则可以使用,
uintpttr\u t SP=(uintptpttr\u t)\u内置\u帧\u地址(0)
。您根本不需要内联程序集。不同之处在于,它会在函数的入口提供堆栈指针,而不是调用站点的当前指针,也就是说,它不会考虑局部变量和其他“临时变量”对堆栈的使用情况。

您必须先将其转换为十六进制字符串。您知道我如何处理这段代码吗?
static __inline__ void printESP(void) {
    static const hexdigit[] = "0123456789ABCDEF\n";
    uintptr_t SP;

    __asm__ __volatile__("mov %%esp, %0\n\t" : "=r"(SP));

    write(1, &hexdigit[SP >> 28], 1);
    write(1, &hexdigit[0xf & SP >> 24], 1);
    write(1, &hexdigit[0xf & SP >> 20], 1);
    write(1, &hexdigit[0xf & SP >> 16], 1);
    write(1, &hexdigit[0xf & SP >> 12], 1);
    write(1, &hexdigit[0xf & SP >> 8], 1);
    write(1, &hexdigit[0xf & SP >> 4], 1);
    write(1, &hexdigit[0xf & SP], 1);
    write(1, &hexdigit[16], 1);
}
static __inline__ printESP(void)
{
    static const char hexdigit[] = "0123456789ABCDEF\n";
    uintptr_t SP;
    char buf[9];

    __asm__ __volatile__("mov %%esp, %0\n\t" : "=r"(SP));

    buf[0] = hexdigit[SP >> 28];
    buf[1] = hexdigit[0xf & SP >> 24];
    buf[2] = hexdigit[0xf & SP >> 20];
    buf[3] = hexdigit[0xf & SP >> 16];
    buf[4] = hexdigit[0xf & SP >> 12];
    buf[5] = hexdigit[0xf & SP >> 8];
    buf[6] = hexdigit[0xf & SP >> 4];
    buf[7] = hexdigit[0xf & SP];
    buf[8] = hexdigit[16];
    write(1, buf, 9);
}