Assembly and Template Classes

I am working on a small project and trying to get some hard-coded values ​​for an inline assembly. For this, I use templates. I created a code snippet to show what I see

#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; } 

It turns out that for the assembly code he is trying to use a data segment, instead of "inserting the number directly there"

  ; 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; 

I am using Visual Studio 2015. Is there any other way to achieve this.

Thank you in advance

Tritron

+5
source share
1 answer

Ah, what a beautiful and twisted question!

I tried the constexpr variable initialized with T. The result was the same - the value loaded from memory. Macros can be used to pass literals to an inline assembly, but they don't mix well with templates.

Initializing an enumeration inside a class using T should in theoretical work ( https://msdn.microsoft.com/en-us/library/ydwz5zc6.aspx mentions that enumerations can be used in the built-in assembly), but using that, the built-in assembly fails Visual Studio 2015 compiler :-).

What seems to work is a function template that declares an enumeration using a template parameter and then uses that enumeration in an inline assembly. If you must have it in the template, you can create an instance of the template function inside the class as follows:

  #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; } 

This leads to the following assembler:

  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)] 
+3
source

Source: https://habr.com/ru/post/1244928/


All Articles