我有点愚蠢,但是我在用C取消对指针的引用(+添加偏移量)感到很苦恼。 我要在C中重新创建的是这种行为:
movabs rax, 0xdeadbeef
add rax, 0xa
mov rax, QWORD PTR [rax]
因此,结尾处的rax应该是:*(0xdeadbeef+0xa)
尤其是与mov rax, QWORD PTR [rax]
等效的方法将是无足轻重的,因为我需要使用计算出的值并检索此时存储的数据(=不同的地址)。
我尝试了很多事情,但这是我目前的阶段:
void *ptr = (void*)0xdeadbeef;
void *ptr2 = *(void*)(ptr+0xa);
翻译成这样的东西:
0x7ffff7fe6050: mov QWORD PTR [rbp-0x38],rax
0x7ffff7fe6054: mov rax,QWORD PTR [rbp-0x38]
0x7ffff7fe6058: add rax,0xa
编辑:它实际上没有编译,在这里提供的C代码中我犯了一个错误,并且无法弄清楚实际上是哪个代码对此编译。无论如何,它并不重要,因为主要目标是将ASM转换为C,现在问题已解决。感谢大家的参与。
因此,前2行基本上没有用,仅将值添加到我的地址中,仅此而已。我需要将其解释为一个地址并在那个时候检索值。
此时存储在那些位置的数据无关紧要。本质上,我想做的就是在内存中找到一个特定的值,并且我知道一种添加偏移量和取消引用指针以达到目标的方法。最后一步只是那一次从我的地址到实际数据类型的类型转换。
我知道这对某些人来说似乎是微不足道的,但是我对C并不十分熟悉,所以我在这里苦苦挣扎...
答案 0 :(得分:3)
您可以通过汇编时完成的数学运算将asm简化为一条指令。 movabs rax, [0xdeadbeef + 0xa]
可以使用从64位绝对地址(https://felixcloutier.com/x86/MOV.html)加载的仅AL / AX / EAX / RAX格式的mov。 (它不适合在32位符号扩展的disp32中使用,因为低32位的高位已设置,与位置相关代码中的普通静态地址不同)。具有32位地址大小覆盖的常规mov
也可以在大约7个字节中工作,因为您的地址确实适合零扩展的32位整数。
在C语言中,您也可以只用一条语句完成整个事情。无需过于复杂:您的地址是指向至的指针,因此您需要将整数转换为x **
类型。
void *ptr = *(const void**)(0xdeadbeefUL + 0xa);
在asm中,指针只是整数,因此使用整数而不是char*
进行数学运算是有意义的。使其成为无符号保证了它零扩展到指针宽度而不是符号扩展。
(尽管C中的数字文字具有足以表示该值的类型,因此,在x86-64编译器上的0xdeadbeef
将是int64_t
(long long
)。实际上不会得到0xdeadbeef
是一个负32位int
,它的符号扩展到0xffffffffdeadbeef
。)
由于void
没有大小,因此无法向void*
添加/减去整数。并且void **
上的指针将成sizeof(void*)
的块。
为避免未定义的行为取消引用void**
(在两个主流x86-64 ABI中均未对齐)的8 = alignof(void*)
,请使用memcpy
。但是我认为您的示例地址只是一个伪造的示例。诸如gcc之类的主流x86编译器不会对未对齐地址做任何奇怪的事情来惩罚UB程序员,因此编译器输出将包含未对齐负载,这些负载在x86上可以正常工作。但是,在自动向量化时,您会遇到这种UB带来的问题。 Why does unaligned access to mmap'ed memory sometimes segfault on AMD64?
但是,如果您出于某种原因想要将其分解为多个asm语句,则您可以将其音译为多个C语句,如下所示:
uintptr_t wheres_the_beef = 0xdeadbeef; // mov eax, 0xdeadbeef
wheres_the_beef += 0xa; // add eax, 0xa
void **address = (void**)wheres_the_beef; // purely a cast, no asm instructions;
void *ptr = *address; // mov rax, [rax]
如果您想为指针添加字节偏移,则可以弄乱char*
,但是这里确实没有意义。
同样,在大多数C实现中,它仍然具有未定义的行为,其中alignof(void*)
大于1,因此void **address = (void**)wheres_the_beef
创建了未对齐的指针。
(有趣的事实:在ISO C中,即使创建未对齐的指针也是UB。但是所有支持Intel内在函数的x86编译器都必须支持创建未对齐的指针,以便将它们传递给_mm_loadu_ps()
之类的内在函数,因此仅实际上取消引用它们是x86编译器上的潜在问题。)