【发布时间】:2018-11-01 10:21:57
【问题描述】:
这是我的 C 程序...我试图打印出 ESP、EBP 和 EIP。
#include <stdio.h>
int main() {
register int i asm("esp");
printf("%#010x <= $ESP\n", i);
int a = 1;
int b = 2;
char c[] = "A";
char d[] = "B";
printf("%p d = %s \n", &d, d);
printf("%p c = %s \n", &c, c);
printf("%p b = %d \n", &b, b);
printf("%p a = %d \n", &a, a);
register int j asm("ebp");
printf("%#010x <= $EBP\n", j);
//register int k asm("eip");
//printf("%#010x <= $EIP\n", k);
return 0;
}
ESP 和 EBP 没有问题。
user@linux:~# ./memoryAddress
0xbffff650 <= $ESP
0xbffff654 d = B
0xbffff656 c = A
0xbffff658 b = 2
0xbffff65c a = 1
0xbffff668 <= $EBP
user@linux:~#
但是当我尝试放置 EIP 代码时,编译时出现以下错误。
user@linux:~# gcc memoryAddress.c -o memoryAddress -g
memoryAddress.c: In function ‘main’:
memoryAddress.c:20:15: error: invalid register name for ‘k’
register int k asm("eip");
^
user@linux:~#
这段代码有什么问题?
register int k asm("eip");
printf("%#010x <= $EIP\n", k);
是否可以通过C编程打印出EIP值?
如果是,请告诉我怎么做。
更新
我在这里测试过代码...
user@linux:~/c$ lscpu
Architecture: i686
CPU op-mode(s): 32-bit
Byte Order: Little Endian
感谢@Antti Haapala 和其他人的帮助。该代码有效......但是,当我将其加载到 GDB 中时,EIP 值是不同的。
(gdb) b 31
Breakpoint 1 at 0x68f: file eip.c, line 31.
(gdb) i r $eip $esp $ebp
The program has no registers now.
(gdb) r
Starting program: /home/user/c/a.out
0x00000000 <= Low Memory Address
0x40055d <= main() function
0x4005a5 <= $EIP 72 bytes from main() function (start)
0xbffff600 <= $ESP (Top of the Stack)
0xbffff600 d = B
0xbffff602 c = A
0xbffff604 b = 2
0xbffff608 a = 1
0xbffff618 <= $EBP (Bottom of the Stack)
0xffffffff <= High Memory Address
Breakpoint 1, main () at eip.c:31
31 return 0;
(gdb) i r $eip $esp $ebp
eip 0x40068f 0x40068f <main+306>
esp 0xbffff600 0xbffff600
ebp 0xbffff618 0xbffff618
(gdb)
这是新代码
#include <stdio.h>
#include <inttypes.h>
int main() {
register int i asm("esp");
printf("0x00000000 <= Low Memory Address\n");
printf("%p <= main() function\n", &main);
uint32_t eip;
asm volatile("1: lea 1b, %0;": "=a"(eip));
printf("0x%" PRIx32 " <= $EIP %" PRIu32 " bytes from main() function (start)\n",
eip, eip - (uint32_t)main);
int a = 1;
int b = 2;
char c[] = "A";
char d[] = "B";
printf("%#010x <= $ESP (Top of the Stack)\n", i);
printf("%p d = %s \n", &d, d);
printf("%p c = %s \n", &c, c);
printf("%p b = %d \n", &b, b);
printf("%p a = %d \n", &a, a);
register int j asm("ebp");
printf("%#010x <= $EBP (Bottom of the Stack)\n", j);
printf("0xffffffff <= High Memory Address\n");
return 0;
}
【问题讨论】:
-
错误消息似乎表明您的汇编程序无法将“eip”识别为可访问寄存器的名称。寄存器名称取决于体系结构,但 GNU 汇编器不会在 i386 的可识别寄存器名称中列出“eip”。
-
但在ARM处理器上不存在,C标准中也没有提到n1570
-
并且要以至少某种 C 方式粗略地了解当前代码的
eip/rip,您可以打印当前函数的地址(它的开头),例如printf("%p\n", &main); -
我将观察到
register int j asm("ebp");实际上并不能保证变量j将在其中具有 EBP 的值,除非它被用作输入(或输入/输出)约束到扩展的内联程序集模板。它在这里工作的事实或多或少是幸运的。 GCC 文档特别强调了这一点
标签: c linux assembly memory x86