程序集和模板类

Assembly and template classes

本文关键字:程序集      更新时间:2023-10-16

我正在做一个小项目,并试图将一些硬编码值用于内联程序集。为此,我正在使用模板。我创建了一个代码截图来显示我所看到的内容

      #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 编译器崩溃:-)。

似乎有效的是一个函数模板,它使用 template 参数声明一个枚举,然后在内联程序集中使用该枚举。如果必须在模板化类中拥有它,则可以在类中实例化模板函数,如下所示:

    #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)]