Visual Studio 2013のC ++を使用したアセンブラー

この記事のアイデアは決して新しいものではありませんが、コンパイルとリンクのエラーをすべて分析し、質問への回答を見つけるのに2日間を費やさなければならなかったので、Habrの読者は時間の節約に値すると判断しました。 プロジェクトで* .asmファイルと* .cppファイルの両方を使用する方法、アセンブラーからC ++メソッドを呼び出す方法、およびその逆をすばやく学習したい人は、catの下で歓迎します。



まえがき



それはすべて、 「Visual Studioを使用したWindows用アセンブラー」という出版物(ほぼ同一のコード)を読むことから始まりました。 彼らはVisual Studio 2005の使用を調査しました。2013年のスタジオではプロセスは似ていますが、準備が整っていないユーザーがアセンブリのすべての問題の解決策を長期にわたって探すことになるいくつかの違いがあります。



内容



  1. TL; DR
  2. プロジェクト作成
  3. 構文の強調表示の設定
  4. C ++とAsmの間でメソッドを呼び出すことの微妙さ
  5. アプリ


TL; DR



読む時間がまったくない人のために:記事の最後(付録)に、完成したプロジェクトテンプレートおよび構文強調表示用のアドオンへのリンクがあります。



プロジェクト作成



イラストバージョン
Visual Studioをオンにして、[ ファイル]-> [新規]-> [プロジェクト...]を選択します



画像



Win32コンソールアプリケーションテンプレートを選択し、[ OK ]をクリックします。



画像



[ 次へ ]をクリックします。



画像



Emptyプロジェクトの前にチェックマークを付けて、 Finishをクリックします。



画像



ソースコードを作成します。 これを行うには、[ ソースファイル ]を右クリックし、[ 追加]-> [新しいアイテム... ]を選択します



画像



C ++ファイルを選択し、[ 追加 ] クリックします。



画像



同様に、* .asmファイルを作成します( 名前フィールドの拡張子を変更するだけです)。



画像



重要:ファイル名は異なる必要があります(拡張子は考慮しません)。そうしないと、* .objファイルを作成するときに、あるオブジェクトファイルを別のオブジェクトファイルで上書きする問題が発生します



これで設定。 プロジェクトを右クリックし、[ 依存関係のビルド ] -> [カスタマイズのビルド... ]を選択します



画像



masmの前にチェックマーク付けて 、[ OK ]をクリックします。



画像



* .asmファイルを右クリックし、[ プロパティ... ]を選択します。



画像



[ アイテムタイプ]フィールドで、[ Microsoft Macro Assembler ]を選択し、[ OK ]をクリックします。



画像



[ プロジェクト]-> [プロパティ...]を選択します。



画像



[ 構成プロパティ]-> [Microsoft Macro Assembler]-> [リストファイル]を選択します[アセンブルされたコードリストファイル]フィールドに$(ProjectName).lstと入力します。



画像



[ 構成プロパティ]-> [リンカー]-> [詳細設定]を選択します 。 [ 画像に安全な例外ハンドラーがあります]フィールドで、[ いいえ]を選択します [ OK ]をクリックします。



画像



この段階では、プロジェクトは作成済みと見なすことができます。 コードの記述については、 C ++とAsm間のメソッド呼び出しの微妙なセクションで説明します。





テキストのみ
Visual Studioをオンにして、[ ファイル]-> [新規]-> [プロジェクト...]を選択します。



Win32コンソールアプリケーションテンプレートを選択し、[ OK ]をクリックします。



次へをクリックします。



Emptyプロジェクトの前にチェックマークを付けて、 Finishをクリックします。



ソースコードを作成します。 これを行うには、[ ソースファイル ]を右クリックし、[ 追加]-> [新しいアイテム... ]を選択します。



[ C ++ファイル ] 選択し、[ 追加 ] クリックします。



同様に、* .asmファイルを作成します([ 名前]フィールドの拡張子を変更するだけです)。



重要:ファイル名は異なる必要があります(拡張子は考慮しません)。そうしないと、* .objファイルを作成するときに、あるオブジェクトファイルを別のオブジェクトファイルで上書きする問題が発生します



これで設定。 プロジェクトを右クリックし、[ 依存関係のビルド ] -> [カスタマイズのビルド... ]を選択します



masmの前にチェックマークを付けて 、[ OK ]をクリックします。



* .asmファイルを右クリックして、[ プロパティ... ]を選択します。



[ アイテムタイプ]フィールドで、[ Microsoft Macro Assembler ]を選択し、[ OK ]をクリックします。



[プロジェクト]-> [プロパティ...]を選択します。



[ 構成プロパティ]-> [Microsoft Macro Assembler]-> [リストファイル]を選択します[アセンブルされたコードリストファイル]フィールドに$(ProjectName).lstと入力します。



[ 構成プロパティ]-> [リンカー]-> [詳細設定]を選択します 。 [ 画像に安全な例外ハンドラーがあります]フィールドで、[ いいえ]を選択します OKをクリックします。



この段階では、プロジェクトは作成済みと見なすことができます。 コードの記述については、 C ++とAsm間のメソッド呼び出しの微妙なセクションで説明します。



構文の強調表示の設定



Visual Studioのアドオン-asmHighlighterがありますが、執筆時点ではVS2013のバージョンはありませんでした。 しかし、ディスカッションセクションを見ると、幸いなことにVS2013のアドオンのバージョンとリポジトリを共有しているTrass3rユーザーからのメッセージが見つかりました。 Visual Studio SDKをインストールした後、プロジェクトをビルドすることができ、* .vsixパッケージが無料で利用できるようになりました



C ++とAsmの間でメソッドを呼び出すことの微妙さ



コンパイルエラーやバインディングエラーを回避するには、次のことに注意してください。

  1. アセンブラからライブラリメソッドを呼び出す必要がある場合は、コードのセクションの冒頭で、使用するメソッドを指定するだけで十分です。



    EXTRN printf : proc ;we'll use printf
          
          





    次に、単にcallを使用できます



     ;printf(ebx,eax) push eax; push ebx call printf add esp, 8 ;pop x2
          
          



  2. カスタムメソッドを呼び出す必要がある場合は、項目1に加えて、メソッドを定義する前にextern“ C”も記述する必要があります。



     extern "C" void* readName() { char* name = (char*)calloc(1, 255); scanf("%s", name); while (getchar() != '\n'); return name; }
          
          





    したがって、* .asmファイルでは:

     EXTRN readName : proc ;and void* readName()
          
          



    そして

     call readName ;eax = readName()
          
          





  3. C ++でAsmメソッドを使用する場合は、プロトタイプを指定するだけです。



     extern "C" { void sayHello(); }
          
          





    このプロトタイプは、次のようなAsmメソッド宣言に対応しています。



     sayHello PROC call readName ;eax = readName() lea ebx, helloFormat ;ebx = &helloFormat ;printf(ebx,eax) push eax push ebx call printf add esp, 8 ;pop x2 retn sayHello ENDP
          
          





実際には、例の完全なソースコード:



Source.cpp
 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> extern "C" { void sayHello(); } void main() { printf("Hello, what is your name?\n"); sayHello(); while (getchar() != '\n'); } extern "C" void* readName() { char* name = (char*)calloc(1, 255); scanf("%s", name); while (getchar() != '\n'); return name; }
      
      







AsmSource.asm
 .686 .MODEL FLAT, C .STACK .DATA ;-----------Local data------------------------------ helloFormat BYTE "Hello, %s!", 10, 13, 0 .CODE ;-----------External usage-------------------------- EXTRN printf : proc;// we'll use printf EXTRN readName : proc;//and void* readName() ;-----------Function definitions-------------------- sayHello PROC call readName; eax = readName() lea ebx, helloFormat; ebx = &helloFormat ;printf(ebx,eax) push eax push ebx call printf add esp, 8;pop x2 retn sayHello ENDP END
      
      









アプリ



完成したプロジェクトテンプレートはこちらにあります

asm構文を強調するためのパッケージはここにあります



PS「に値する」修正についてilynxyに感謝します))



All Articles