2017-08-03 17 views
2

コンパイラについて少し勉強しようとしています。私はNASMを使用して私のオブジェクトファイルをコンパイルし、dllに変換するためにalinkを使用しています。依存関係ウォーカーを使用して、私のdllの内容を確認しています。これまでのところ、コードで私のdllをコンパイルするのが得意で、GetProcAddressでそれを取得できます。しかし、私はそれを起動しようとすると、私は次のエラーを取得する:私はエラーを取得する理由C#で基本的なコンパイラを作成しようとしましたが、アクセス違反エラーが発生しました

Unhandled Exception: System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

私はすべてがそうではない1〜100%eaxに設定されています。私はどのメモリが壊れているかわからない、私はこのDLLを適切に呼び出すために何ができるかについての援助は非常に高く評価されるだろう。

編集:Windows x64上で32ビットアセンブリを使用していますが、動作するかどうかを確認するためにx64アセンブリ/アセンブラを試している可能性があります。

動的に生成されたアセンブリファイル

global DllMain 
export DllMain 

global testfunc 
export testfunc 

section .code use32 

DllMain:  ; This code is required in .dll files 
mov eax,1 
ret 12 

testfunc: 
mov eax, 1 
ret 

C#コード

namespace KCompiler 
    { 
     public static class NativeMethods 
     { 
      [DllImport("kernel32.dll")] 
      public static extern IntPtr LoadLibrary(string dllToLoad); 

      [DllImport("kernel32.dll")] 
      public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName); 
      [DllImport("kernel32.dll")] 
      public static extern bool FreeLibrary(IntPtr hModule); 
     } 

     class Program 
     { 
      [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 
      delegate int TestFuncDelegate(); 
      static int Main(string[] args) 
      { 
       /* 
       AntlrFileStream stream = new AntlrFileStream("../../example.k"); 
       CLexer lexer = new CLexer(stream); 
       CommonTokenStream tokens = new CommonTokenStream(lexer); 
       CParser parser = new CParser(tokens); 
       ParseTreeWalker tree = new ParseTreeWalker(); 
       CListener listener = new CListener(); 
       tree.Walk(listener, parser.file()); 
       */ 

       KAssembler assembler = new KAssembler(); 

       //assembler.PushR("ebp"); 
       //assembler.Mov32RR("ebp", "esp"); 
       assembler.Mov32RI("eax", 1); 
       //assembler.PopR("ebp"); 
       assembler.Return(); 

       string RelativeDirectory = @"..\.."; 
       string fullAssembly = File.ReadAllText(Path.Combine(RelativeDirectory,"k_template.asm")).Replace("{ASSEMBLY}", assembler.ToString()); 
       Console.WriteLine(fullAssembly); 
       File.WriteAllText(Path.Combine(RelativeDirectory,"k.asm"), fullAssembly); 

       ProcessStartInfo nasmInfo = new ProcessStartInfo() 
       { 
        UseShellExecute = false, 
        FileName = Path.Combine(RelativeDirectory,"nasm.exe"), 
        RedirectStandardOutput = true, 
        Arguments = @"-fobj ..\..\k.asm", 
       }; 

       using (Process nasm = Process.Start(nasmInfo)) 
       { 
        nasm.WaitForExit(); 
        Console.WriteLine($"NASM exited with code: {nasm.ExitCode}"); 
        if (nasm.ExitCode != 0) return nasm.ExitCode; 
       } 

       ProcessStartInfo alinkInfo = new ProcessStartInfo() 
       { 
        UseShellExecute = false, 
        FileName = Path.Combine(RelativeDirectory,"alink.exe"), 
        RedirectStandardOutput = true, 
        Arguments = Path.Combine(RelativeDirectory,"k.obj") + " -oPE -dll", 
       }; 

       using (Process alink = Process.Start(alinkInfo)) 
       { 
        alink.WaitForExit(); 
        Console.WriteLine($"alink exited with code: {alink.ExitCode}"); 
        if (alink.ExitCode != 0) return alink.ExitCode; 
       } 

       IntPtr dll = new IntPtr(0); 
       try 
       { 
        dll = NativeMethods.LoadLibrary(Path.Combine(RelativeDirectory, "k.dll")); 
        Console.WriteLine(dll.ToInt32() == 0 ? "Unable to Load k.dll" : "Loaded k.dll"); 
        if (dll.ToInt32() == 0) return 1; 

        IntPtr TestFunctionPtr = NativeMethods.GetProcAddress(dll, "testfunc"); 
        Console.WriteLine(TestFunctionPtr.ToInt32() == 0 ? "Unable to Load 'testfunc'" : "Loaded 'testfunc'"); 
        if (TestFunctionPtr.ToInt32() == 0) return 1; 

        TestFuncDelegate Test = Marshal.GetDelegateForFunctionPointer<TestFuncDelegate>(TestFunctionPtr); 

        int result = Test(); //Error right here 
        Console.WriteLine($"Test Function Returned: {result}"); 
       } 
       finally 
       { 
        if(dll.ToInt32() != 0) 
         NativeMethods.FreeLibrary(dll); 
       } 

       return 0; 
      } 
     } 
    } 
+0

私が直接あなたを助けることはできませんが、あなたの場所で私が最初に 'Cに7'返すのと同等の代わりに、DLLのいくつかの基本的なexeファイルを、作成します、これが動作すれば、私はCまたはC++プログラムでこのDLLを読み込もうとします。あなたは何が間違っているかを見つけるためにステップバイステップで知っています。 – greenoldman

+0

私はyaを持っていました、私は約45分を過ぎてから仕事に行く前にそれを昨晩デバッグしました。私は何かを働かせたら、私が終わったらここにそれを掲示するでしょう。これは良いアイデアです、そして、x64アセンブリを試してみることは、私が今夜試してみるものになるでしょう。 – user2927848

答えて

0

さてさて、私は解決策を見つけました。 alinkは-fwin32形式をdllにリンクするのが難しかったので、私はgolinkリンカーに切り替えました。だから今私はgolinkリンカで NASMアセンブラを使用しており、前と同じ設定で動作させることができました。コードは以下のとおりです。

また、[ビット#]をコードの先頭に置かないと、デフォルトで16ビットモードになります。そのため、32ビットに切り替える必要があります。 64を置く場合は、64ビットアセンブリを作成して動作させる必要があります。

ASMコード

[bits 32] 
global DllMain 
global testfunc 

export DllMain 
export testfunc 

section .text 

DllMain:  ; This code is required in .dll files 
mov eax,1 
ret 12 

testfunc: 
mov eax, 32 
ret 

C#コード

using System; 
using Antlr4; 
using System.IO; 
using Antlr4.Runtime; 
using Antlr4.Runtime.Misc; 
using Antlr4.Runtime.Tree; 
using System.Collections.Generic; 
using KCompiler.KCore; 
using KCompiler.Assembler; 
using System.Diagnostics; 
using System.Runtime.InteropServices; 

namespace KCompiler 
{ 
    public static class NativeMethods 
    { 
     [DllImport("kernel32.dll")] 
     public static extern IntPtr LoadLibrary(string dllToLoad); 

     [DllImport("kernel32.dll")] 
     public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName); 
     [DllImport("kernel32.dll")] 
     public static extern bool FreeLibrary(IntPtr hModule); 
    } 

    class Program 
    { 
     [UnmanagedFunctionPointer(CallingConvention.StdCall)] 
     delegate int TestFuncDelegate(); 
     static int Main(string[] args) 
     { 
      /* 
      AntlrFileStream stream = new AntlrFileStream("../../example.k"); 
      CLexer lexer = new CLexer(stream); 
      CommonTokenStream tokens = new CommonTokenStream(lexer); 
      CParser parser = new CParser(tokens); 
      ParseTreeWalker tree = new ParseTreeWalker(); 
      CListener listener = new CListener(); 
      tree.Walk(listener, parser.file()); 
      */ 

      KAssembler assembler = new KAssembler(); 
      assembler.Mov32RI("eax", 32); 

      string RelativeDirectory = @"..\.."; 
      string fullAssembly = File.ReadAllText(Path.Combine(RelativeDirectory,"k_template.asm")).Replace("{ASSEMBLY}", assembler.ToString()); 
      Console.WriteLine(fullAssembly); 
      File.WriteAllText(Path.Combine(RelativeDirectory,"k.asm"), fullAssembly); 

      ProcessStartInfo nasmInfo = new ProcessStartInfo() 
      { 
       UseShellExecute = false, 
       FileName = Path.Combine(RelativeDirectory,"nasm.exe"), 
       RedirectStandardOutput = true, 
       Arguments = @"-fwin32 "+ Path.Combine(RelativeDirectory,"k.asm") 
      }; 

      using (Process nasm = Process.Start(nasmInfo)) 
      { 
       nasm.WaitForExit(); 
       Console.WriteLine($"NASM exited with code: {nasm.ExitCode}"); 
       if (nasm.ExitCode != 0) return nasm.ExitCode; 
      } 

      ProcessStartInfo golinkInfo = new ProcessStartInfo() 
      { 
       UseShellExecute = false, 
       FileName = Path.Combine(RelativeDirectory,"GoLink.exe"), 
       RedirectStandardOutput = true, 
       //Arguments = Path.Combine(RelativeDirectory,"k.obj") + " -c -oPE -dll -subsys windows", 
       Arguments = Path.Combine(RelativeDirectory, "k.obj") + " /dll", 
      }; 

      using (Process golink = Process.Start(golinkInfo)) 
      { 
       golink.WaitForExit(); 
       Console.WriteLine($"alink exited with code: {golink.ExitCode}"); 
       if (golink.ExitCode != 0) return golink.ExitCode; 
      } 

      IntPtr dll = new IntPtr(0); 
      try 
      { 
       dll = NativeMethods.LoadLibrary(Path.Combine(RelativeDirectory, "k.dll")); 
       Console.WriteLine(dll.ToInt32() == 0 ? "Unable to Load k.dll" : "Loaded k.dll"); 
       if (dll.ToInt32() == 0) return 1; 

       IntPtr TestFunctionPtr = NativeMethods.GetProcAddress(dll, "testfunc"); 
       Console.WriteLine(TestFunctionPtr.ToInt32() == 0 ? "Unable to Load 'testfunc'" : "Loaded 'testfunc'"); 
       if (TestFunctionPtr.ToInt32() == 0) return 1; 
       TestFuncDelegate Test = Marshal.GetDelegateForFunctionPointer<TestFuncDelegate>(TestFunctionPtr); 
       int result = Test(); 
       Console.WriteLine($"Test Function Returned: {result}"); 
      } 
      finally 
      { 
       if(dll.ToInt32() != 0) 
        NativeMethods.FreeLibrary(dll); 
      } 

      return 0; 
     } 
    } 
} 
関連する問題