我正在开发一个小项目,并尝试将一些硬编码值用于内联汇编。为此,我使用模板。我创建了一个代码片段来显示我所看到的
#include <iostream>
template <size_t T>
struct MyClass
{
size_t myValue = T;
void doSomething()
{
size_t value = T;
__asm
{
mov eax, [T]
mov [value], eax
}
std::cout << value << std::endl;
}
};
int main()
{
auto o = new MyClass<999>();
o->doSomething();
return 0;
}
事实证明,对于汇编代码,它试图使用数据段而不是“直接将数字粘贴到那里”
; 25 : {
push ebp
mov ebp, esp
push ecx
; 26 : auto o = new MyClass<999>();
push 4
call ??2@YAPAXI@Z ; operator new
add esp, 4
; 14 : size_t value = T;
mov DWORD PTR _value$2[ebp], 999 ; 000003e7H
; 26 : auto o = new MyClass<999>();
mov DWORD PTR [eax], 0
mov DWORD PTR [eax], 999 ; 000003e7H
; 15 : __asm
; 16 : {
; 17 : mov eax, [T]
mov eax, DWORD PTR ds:0
; 18 : mov [value], eax
mov DWORD PTR _value$2[ebp], eax
; 19 : }
; 20 : std::cout << value << std::endl;
我正在使用 Visual Studio 2015。还有其他方法可以实现此目的吗?
啊,多么可爱又扭曲的问题啊!
我尝试使用 T 初始化 constexpr 变量。结果是相同的 - 从内存加载值。宏可用于将文字传递给内联汇编,但它们与模板不能很好地混合。
使用 T 在类中初始化枚举在理论上应该可行(https://msdn.microsoft.com/en-us/library/ydwz5zc6.aspx提到枚举可以在内联汇编中使用),但是在内联汇编使 Visual Studio 2015 编译器崩溃:-)。
似乎有效的是一个函数模板,它使用模板参数声明一个枚举,然后在内联程序集中使用该枚举。如果必须将其放在模板类中,则可以在类中实例化模板函数,如下所示:
#include <iostream>
template <size_t T> void dosomething() {
enum { LOCALENUM = T };
size_t value = 0;
__asm
{
mov eax, LOCALENUM
mov[value], eax
}
std::cout << value << std::endl;
}
template <size_t T>
struct MyClass
{
size_t myValue = T;
void doSomething()
{
::dosomething<T>();
}
};
int main()
{
//dosomething<999>();
auto o = new MyClass<999>();
o->doSomething();
return 0;
}
这会产生以下汇编代码:
auto o = new MyClass<999>();
001B1015 mov dword ptr [eax],0
001B101B mov dword ptr [eax],3E7h
o->doSomething();
001B1021 mov eax,3E7h <--- Victory!
001B1026 mov dword ptr [ebp-4],eax
001B1029 mov ecx,dword ptr [_imp_?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A (01B2048h)]
001B102F push offset std::endl<char,std::char_traits<char> > (01B1050h)
001B1034 push dword ptr [ebp-4]
001B1037 call dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (01B2044h)]