我在VS中有一个函数,我传递一个指向函数的指针。然后我想将指针存储在寄存器中以进一步操作。你是怎么做到的?
我试过了
float __declspec(align(16)) x[16] =
{
0.125000, 0.125000, 0.125000, 0,
-0.125000, 0.125000, -0.125000, 0,
0.125000, -0.125000, -0.125000, 0,
-0.125000, -0.125000, 0.125000, 0
};
void e()
{
__asm mov eax, x // doesn't work
__asm mov ebx, [eax]
}
void f(float *p)
{
__asm mov eax, p // does work
__asm mov ebx, [eax]
}
int main()
{
f(x);
e();
}
答案 0 :(得分:3)
选项1实际上似乎工作正常。请考虑以下程序:
#include <stdio.h>
void f(int *p) {
__asm mov eax, p
__asm mov ebx, [eax]
// break here
}
void main()
{
int i = 0x12345678;
f(&i);
}
使用Visual Studio 2008 SP1,单文件C ++程序和调试版本,当我步入f()的末尾时,我在寄存器窗口中得到以下内容:
EAX = 004DF960
EBX = 12345678
ECX = 00000000
EDX = 00000001
ESI = 00000000
EDI = 004DF884
EIP = 003013C3
ESP = 004DF7B8
EBP = 004DF884
EFL = 00000202
查看EAX,EBX和ESP中的值,这看起来像是一个非常好的证据,表明你实际上拥有了你想要的指针。 EAX中的地址比ESP中的地址略高,这表明它在堆栈中高出一帧。加载到EBX中的解除引用值表明我们得到了正确的地址。
加载全局地址略有不同。以下示例使用LEA指令完成任务。
#include <stdio.h>
int a[] = { 0x1234, 0x4567 };
void main()
{
// __asm mov eax, a ; interpreted as eax <- a[0]
__asm lea eax, a ; interpreted as eax <- &a[0]
__asm mov ebx, [eax]
__asm mov ecx, [eax+4]
// break here
}
单步执行main()可以获得以下寄存器值。 EAX获取数组中第一个元素的地址,而EBX和ECX获取其成员的值。
EAX = 00157038
EBX = 00001234
ECX = 00004567
EDX = 00000001
ESI = 00000000
EDI = 0047F800
EIP = 001513C9
ESP = 0047F734
EBP = 0047F800
EFL = 00000202
神奇不在LEA指令本身。相反,似乎__asm指令根据是使用MOV还是LEA指令来区别对待C / C ++标识符。当取消注释MOV指令时,这是同一程序的ASM转储。注意MOV指令如何获取[]的内容作为其参数(DWORD PTR),而LEA指令获取其偏移量。
; ...
PUBLIC ?a@@3PAHA ; a
_DATA SEGMENT
?a@@3PAHA DD 01234H ; a
DD 04567H
_DATA ENDS
; ...
mov eax, DWORD PTR ?a@@3PAHA
lea eax, OFFSET ?a@@3PAHA
mov ebx, DWORD PTR [eax]
mov ecx, DWORD PTR [eax+4]
; ...
答案 1 :(得分:1)
我不确定这是否正确,但您是否尝试先将* p转换为int然后加载该值?
void f(*p)
{
int tmp = (int)p;
// asm stuff...
}