Frage

Ich erstelle eine Ausgabe für eine ausführbare .Net-Datei aus meiner eigenen Sprache ...Der Opcode (genannt „Random“), der aus meiner Sprache übersetzt wird, soll eine Zufallszahl innerhalb eines bestimmten Bereichs erzeugen.

Das Ziel meines Codes besteht darin, die Zufallszahl mithilfe der System.Reflection.Emit.ILGenerator-Klasse zu erzeugen ...Um zu verstehen, wie der CIL-Code aussieht, habe ich einen vb.net-Code erstellt:

Sub Main()
    Dim A As Random

    A = New Random

    Console.WriteLine(A.Next(100))
End Sub

Welches ILDASM meldet als:

.method public static void  Main() cil managed
{
  .entrypoint
  .custom instance void [mscorlib]System.STAThreadAttribute::.ctor() = ( 01 00 00 00 ) 
  // Code size       23 (0x17)
  .maxstack  2
  .locals init ([0] class [mscorlib]System.Random A)
  IL_0000:  nop
  IL_0001:  newobj     instance void [mscorlib]System.Random::.ctor()
  IL_0006:  stloc.0
  IL_0007:  ldloc.0
  IL_0008:  ldc.i4.s   100
  IL_000a:  callvirt   instance int32 [mscorlib]System.Random::Next(int32)
  IL_000f:  call       void [mscorlib]System.Console::WriteLine(int32)
  IL_0014:  nop
  IL_0015:  nop
  IL_0016:  ret
} // end of method Main::Main

Ich kann alles mit der ILGenerator.Emit-Methode reproduzieren.außer der Zeile IL_0001 („newobj case void [mscorlib]System.Random::.ctor()“) ...

Hoffentlich habe ich niemanden mit zu vielen Informationen überfordert.Aber ich denke, es ist besser, ausführlich zu sein, wenn man ein Problem beschreibt, das mir komplex erscheint.

Endlich habe ich den Code, den ich bisher erstellt habe:

 Sub EmitRandom()
    Dim NewRandom As New Random
    Dim stringtype As Type = GetType(System.Random)

    Dim paramtypes() As Type = {GetType(Integer)}, blankparams() As Type = {}
    'Dim RandomMethod = stringtype.GetMethod("New", paramtypes)

    m_ILGen.Emit(OpCodes.Newobj, New Random().GetType)

    EmitStoreInLocal(tempVariableRnd)
    EmitLoadLocal(tempVariableRnd)

    m_ILGen.Emit(OpCodes.Callvirt, stringtype.GetMethod("Next", paramtypes))
End Sub

Was den folgenden Code ausgibt:

.
.
.
IL_0073:  newobj     [mscorlib]System.Random
IL_0078:  stloc.2
IL_0079:  ldloc.2
IL_007a:  callvirt   instance int32 [mscorlib]System.Random::Next(int32)
.
.
.

Dinge, die ich bereits ausprobiert habe:

  • Überlegen Sie sich eine Möglichkeit, auf IL_Gen.Emit(OpCodes.NewObj, ...) zu verweisen.ctor())...Ich kann nicht herausfinden, wie.

  • Überlegen Sie sich eine Möglichkeit, auf New() zu verweisen – denn das scheint .ctor() zu sein ...New kann nur als Initialisierer verwendet werden.

  • Deaktiviere einfach die Zufallsfunktion, bis ich eine bessere Möglichkeit zum Emittieren gefunden habe.

Das Problem scheint mir schwierig zu sein, aber ich weiß, dass es da draußen jemanden gibt, der Codegenerierung und MSIL besser versteht als ich und der bereit ist, eine Antwort zu geben.

Vielen Dank für Ihre Zeit,

Dominick

War es hilfreich?

Lösung

Sie müssen die ConstructorInfo verwenden:

 m_ILGen.Emit(OpCodes.Newobj, GetType(Random).GetConstructor(Type.EmptyTypes))

Außerdem ist das Speichern und Laden von lokal nicht erforderlich.Sie wollen eigentlich nur das Äquivalent von new Random().Next(100), oder? ... in diesem Fall findet das Speichern und Laden von einem lokalen Ort nie statt.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top