【发布时间】:2019-05-05 13:21:55
【问题描述】:
代码如下:
__declspec ( naked ) void nseel_asm_assign(void)
{
__asm
{
fld qword ptr [eax]
fstp qword ptr [ebx]
}
}
__declspec ( naked ) void nseel_asm_assign_end(void) {}
使用它们的代码崩溃。调试器显示地址正常,例如
&nseel_asm_assign 0x0f45e4a0 {vis_avs.dll!nseel_asm_assign(void)} void(*)()
&nseel_asm_assign_end 0x0f45e4b0 {vis_avs.dll!nseel_asm_assign_end(void)} void(*)()
但是,当这些函数的地址由实际的 C 代码而不是由调试器获取时,它就不再正确并且消费代码由于大小为负而崩溃:
fn 0x0f455056 {vis_avs.dll!_nseel_asm_assign} void(*)()
fn_e 0x0f45295f {vis_avs.dll!_nseel_asm_assign_end} void(*)()
带下划线的函数只包含一条指令,例如jmp nseel_asm_assign
如何获取实函数的地址,不带下划线?
更新:如果您想知道我为什么要编写这样的代码,那不是我,it’s third party,而且它在使用 VC++ 6.0 构建时运行良好。
【问题讨论】:
-
“因为大小是负数”鉴于
size_t未签名,这怎么可能? -
另外,您使用的是什么工具链和编译器(和版本)?您的目标是什么平台?
-
@Dai 消费代码是一个 JIT 编译器,它通过减去这两个函数的地址来计算大小,然后复制函数的代码。 Win32,VC++ 2017。
-
naked表示编译器不会为您发出ret指令,或任何将指针放入寄存器的设置。您没有展示您如何“使用”此代码,但您将得到的只是 2 个 asm 指令上的标签,然后进入下一步。 -
您需要使用 /Zi 而不是 /ZI 进行编译,以击败 MSVC++ 用于支持增量链接和编辑+继续的技巧。查看报告的地址,您现在应该会在那里看到一条跳转到实际代码的 JMP 指令。修改 JMP 目标是允许链接器和调试器随意替换函数的原因。这无助于您测量函数大小和移动代码。
标签: c windows visual-c++ inline-assembly function-address