将 Visual Studio asm 移植到 g++ basic asm

时间:2020-12-27 12:50:27

标签: c++ assembly gcc visual-c++ inline-assembly

我有以下简单但令人沮丧的问题:我使用的是 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++ 程序的东西。 g++ asm 在没有扩展 asm 的情况下不能轻易使用 c++ 的东西。 __declspec(naked) 阻止我使用扩展 asm。

-我不知道“retn”是做什么的,所以我不能用等效的代码来伪造它。

编辑:我使用的是 Windows。

目的是构建一个 .dll 供 OBSE 用于 TES Oblivion。我正在用 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;
}
};

1 个答案:

答案 0 :(得分:1)

我不确定它是否适合您,但您可以使用 clang(-fasm-blocks 开关)编译 msvc stile 程序集。

以下是成功编译 asm 的示例:https://godbolt.org/z/o57sbq

不确定它是否适合您,因为 clang 不是 gcc,但只是想提一下。也许它会有所帮助。请不要杀我。

相关问题