【发布时间】:2016-10-22 03:51:48
【问题描述】:
我正在尝试在 Visual Studio 2015 中与 _asm _emit 一起实现布尔运算,想在 x86 程序中插入一些 x64 操作码,我必须对内存命令做很多 mov,所以我尝试制作某种宏,获取地址并以 little-endian 形式发出,因此:
#define EmitDword(x)\
{\
_asm _emit (x & 0x000000FF) \
_asm _emit ((x >> 8) & 0x000000FF) \
_asm _emit ((x >> 16) & 0x000000FF) \
_asm _emit ((x >> 24) & 0x000000FF) \
}
但我收到一个错误inline assembler syntax error in 'first operand';
这个想法是,将变量的地址传递给宏,因此它会直接发送到机器代码中,然后我可以这样做:
#define EmitDword(x)\
{\
_asm _emit (x & 0x000000FF) \
_asm _emit ((x >> 8) & 0x000000FF) \
_asm _emit ((x >> 16) & 0x000000FF) \
_asm _emit ((x >> 24) & 0x000000FF) \
}
/* mov qword ptr [addr],reg */
#define X64_MovToMem(addr,reg)\
{\
_asm _emit 0x48\
_asm _emit 0x89\
_asm _emit reg\
_asm _emit 0x25\
EmitDword(addr)\
}
#define _rax 4
void test()
{
DWORD64 someData;
X64_MovToMem(&someData,_rax);
}
有没有办法使用预处理器内联汇编实现非常量值的发射?
【问题讨论】:
-
不,您发送到编译器的 asm 输出中的每个字节都必须是编译时常量。我怀疑您是否会通过这种尝试解决仅在 32 位模式下支持
_asm的 MSVC 来创建有用的 x86-64 代码的运气。您可能应该只在 asm 中编写函数并从 C++ 中调用它们,因为没有办法告诉编译器您插入的任何指令的操作。 -
另请注意,地址是链接时常量,而不是真正的编译时,因此用宏分割地址是行不通的:编译器和汇编器不能分别知道每个字节,并且只需要留出空间并在目标文件的符号表中放置一个重定位。该值将由链接器在链接时填写。
-
如果您只需要 asm 指令作为数据,并且自己编码,为什么不使用 struct 和 memcpy?
标签: c visual-c++ assembly c-preprocessor inline-assembly