2016-03-12 4 views
4

Я работаю над небольшим проектом и пытаюсь получить некоторые жестко заданные значения для встроенной сборки. Для этого я использую шаблоны. Я создал код надрез, чтобы показать, что я вижуСборочные и шаблонные классы

 #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 [email protected]@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. Есть ли другой способ достичь этого.

Заранее благодарна

Tritron.

+2

я не видел шаблон и код сборки смешанный. Смелая душа, вы есть. –

+1

Если 'T' - значение, вы не должны использовать' mov eax, T', а не '[T]'? –

+0

Да, но аналогичный результат, если используется значение. Кажется, он заменяется на 0. ds - это то, что вы измеряете. – tritron

ответ

2

Ах, какой прекрасный и искривленный вопрос!

Я попробовал переменную constexpr, инициализированную T. Результат был тот же - значение, загруженное из памяти. Макросы могут использоваться для передачи литералов в встроенную сборку, но они не хорошо сочетаются с шаблонами.

Инициализация перечисления внутри класса с использованием 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   [[email protected]@@[email protected][email protected]@[email protected]@@[email protected] (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)] 
+0

Кажется, проблема связана с классами. Это может быть ошибка, о которой вы упоминаете, но ответ, который вы предоставили, полезен в моем случае. Я могу передать этот параметр этой функции. Благодарю. – tritron

+1

На самом деле, кажется, что вы можете переместить функцию dosomething() в ответ как функцию-член внутри класса, когда enum объявлен внутри функции. Кажется, что просто объявление enum в области класса сбой компилятора. –

+0

Ницца, спасибо еще раз. – tritron

Смежные вопросы