我有一个简单但令人沮丧的问题:我使用的是g++编译器,但我使用的示例代码是为Visual Studio编写的。通常不是问题,但它们的内联汇编程序的工作方式不同,因此需要更改代码。
问题所在的片段如下:
float someotherfuncname(inputvar)
{
//For example purposes. Can be arbitrary amount of math.
return 1;
}
void __declspec(naked)funcname(void)
{
__asm
{
push ecx
call someotherfuncname
pop ecx
retn
}
}我在这个话题上没有经验,基本上我是在小心翼翼地复制一个更有经验的程序员写的神秘公式,希望能重现结果(在其他部分取得成功,但这个部分得到了我的支持)。
据我所知,主要的问题是:
-g++ asm没有"retn“。
-"call“使用来自周围c++程序的东西。没有扩展的asm,g++ asm不能很容易地使用c++的东西。__declspec(裸体)阻止我使用扩展的asm。
-I不知道"retn“是做什么的,所以我不能用等价的代码来伪造它。
编辑:我正在使用Windows。
其目的是构建一个供OBSE用于TES遗忘的.dll。我正在用g++ (可能是MinGW)构建它。
一个(非)工作代码的最小草图是:在.h文件中(这不是问题,只是为了完整性):
#ifndef MSK_B
#define MSK_B
#ifdef __cplusplus
extern "C" {
#endif
#ifdef DLL_KOMP
#define SPECK __declspec(dllexport)
#else
#define SPECK __declspec(dllexport)
#endif
bool SPECK OBSEPlugin_Query(const OBSEInterface * obse, PluginInfo * info);
bool SPECK OBSEPlugin_Load(const OBSEInterface * obse);
#ifdef __cplusplus
}
#endif
#endif // MMC_B_H在.cpp文件中:注意,这里没有定义OBSEInterface和PluginInfo,但也不需要它们(只有一些框架定义可以让编译器满意,所以我省略了它们)。
include "[name of the .h file]"
include <fstream>
include "Windows.h"
typedef unsigned long UInt32
void SafeWrite8(UInt32 addr, UInt32 data)
{
UInt32 oldProtect;
VirtualProtect((void *)addr, 4, PAGE_EXECUTE_READWRITE, &oldProtect);
*((UInt8 *)addr) = data;
VirtualProtect((void *)addr, 4, oldProtect, &oldProtect);
}
void SafeWrite32(UInt32 addr, UInt32 data)
{
UInt32 oldProtect;
VirtualProtect((void *)addr, 4, PAGE_EXECUTE_READWRITE, &oldProtect);
*((UInt32 *)addr) = data;
VirtualProtect((void *)addr, 4, oldProtect, &oldProtect);
}
void WriteRelPaddedCall(UInt32 strtAddr, UInt32 retnAddr, UInt32 callbackAddr)
{
for (UInt32 i = strtAddr; i < retnAddr; i++) SafeWrite8(i,0x90);
WriteRelCall(strtAddr,callbackAddr);
}
extern "C" {
bool SPECK OBSEPlugin_Query(const OBSEInterface * obse, PluginInfo * info)
{
return true;
}
bool SPECK OBSEPlugin_Load(const OBSEInterface * obse)
{
UInt32 RuesDispAddrH = 0x005AB365;
UInt32 RuesDispAddrR = 0x005AB36D;
//RuestungECX is the function i posted above.
//This line (as implemented here) causes the game to crash when loading a game (or starting a new game).
WriteRelPaddedCall(RuesDispAddrH, RuesDispAddrR, (UInt32) &RuestungECX);
return true;
}
};发布于 2020-12-27 23:02:25
我不确定它是否适合你,但你可以用clang (-fasm-blocks开关)编译msvc stile程序集。
下面是一个成功编译的asm示例:https://godbolt.org/z/o57sbq
不确定这是不是一个很好的选择,因为轰隆不是一个gcc,但只是想提一下。也许这对你有帮助。请不要杀我。
https://stackoverflow.com/questions/65465946
复制相似问题