2

Hello i am generating a class using Reflection.Emit and i want to know how do you use brfalse command for conditionals.

Specifically i do not know how do i translate the IL to OPCODES for the brfalse.s command.

My method has the following form:

object MyMethod() { if(isTransaction) //isTransaction is a bool property return Method1(); else return Method2(); }

Conditional

        IL_0000: ldarg.0      // this
        IL_0001: call         instance bool RediusTests.DaemonBase::get_IsTransaction()
        IL_0006: brfalse.s    IL_0020    //how is this translated within opcodes?

First branch:

        IL_0008:ldarg_0
        IL_.......          ///INSTRUCTIONS
        IL_......
        IL_001f:ret

Second branch:

        IL_0020:ldarg_0     //How do i specify with OPCODES to jump here?????
        IL_.......          
        IL_......
        IL_001f:ret

For the first snippet what would be the argument of brfalse.s?

        ilgen.Emit(OpCodes.Ldarg_0);
        ilgen.Emit(OpCodes.Call, getIsTransaction);
        ilgen.Emit(OpCodes.Brfalse,);  //what do i put here in the overload?

As you can see in the last snippet ,last line ,what should i put in the overload of ilgen.Emit? Nothing , 20 or is there some other code for translating to IL_0020?

Also isn't the address of the instruction stored at different address of memory on every run of program?Couldn't it change from IL0020 to IL00xx at future executions?

P.S After receiveing some comprehensive answers this is my version so far:

        ILGenerator ilgen = newMethod.GetILGenerator();
        Label falseLabel = ilgen.DefineLabel();
        Label continueLabel = ilgen.DefineLabel();

        ilgen.Emit(OpCodes.Ldarg_0);       
        ilgen.Emit(OpCodes.Call, getIsTransaction);
        ilgen.Emit(OpCodes.Brtrue,continueLabel);   //branching

        ilgen.MarkLabel(continueLabel);    //true branch
        ----instructions------
        ilgen.Emit(OpCodes.Ret);
        ilgen.Emit(OpCodes.Br,continueLabel);

        ilgen.MarkLabel(falseLabel);     //false branch
        --instructions----
        ilgen.Emit(OpCodes.Ret);
Bercovici Adrian
  • 8,794
  • 17
  • 73
  • 152
  • IIRC brfalse.s should make short jump, i.e. a relative jump taking the difference between the offset of the target instruction and offset of the current/brfalse.s instruction. – ckuri Sep 27 '18 at 07:09
  • You need to define and reference labels – vc 74 Sep 27 '18 at 07:09
  • But like @vc74 said if you use the Emit class you would need to define a label, so the Emit class can calculate the offset difference for you. – ckuri Sep 27 '18 at 07:12

1 Answers1

5

You never have to deal with code addresses explicitly. In order to jump, you need to define labels:

Label falseLabel = ilgen.DefineLabel();
Label continueLabel = ilgen.DefineLabel();

ilgen.Emit(OpCodes.Call, getIsTransaction);
ilgen.Emit(OpCodes.Brfalse, continueLabel);

// getIsTransaction returned true
...

ilgen.Emit(OpCodes.Br, continueLabel);

ilgen.MarkLabel(falseLabel);
// getIsTransaction returned false
...

ilgen.MarkLabel(continueLabel);
vc 74
  • 37,131
  • 7
  • 73
  • 89
  • Oh i did not know.Thank you very much ! But why do you need the `ilgen.Emit(OpCodes.Br,continueLabel)`?Don't you need just the `BrFalse` expression and the 2 `MarkLabel`-s ? – Bercovici Adrian Sep 27 '18 at 07:44
  • 1
    If you don't `br` after the true result handling, the false result handling will be executed too – vc 74 Sep 27 '18 at 07:52
  • And so the `MarkLabel`-s must be placed right before the first instruction of the `True` and `False` branch ? – Bercovici Adrian Sep 27 '18 at 07:54
  • 1
    Exactly, just like addresses – vc 74 Sep 27 '18 at 07:56
  • Ok so i would have : `brfalse` -> `MarkLabel(true) `->`[ branch instructions ..->ret ] `->`br`->`MarkLabel(false)`->` [ branch instructions ... ret]`? – Bercovici Adrian Sep 27 '18 at 07:58
  • 1
    You don't need the rets if it's all in a single method (unless you want to exit that method in which case you don't need the continue label) – vc 74 Sep 27 '18 at 08:10
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/180855/discussion-between-bercovici-adrian-and-vc-74). – Bercovici Adrian Sep 27 '18 at 08:10