I'm currently facing new problem with operators. Using following code, I want to make output that would be same as when using if ... else pair in C#.
var method = new DynamicMethod("dummy", null, Type.EmptyTypes);
var g = method.GetILGenerator();
g.Emit(OpCodes.Ldstr, "string");
g.Emit(OpCodes.Ldstr, "string");
g.Emit(OpCodes.Call, typeof(String).GetMethod("op_Equality", new Type[]{typeof(string), typeof(string)}));
g.Emit(OpCodes.Ldc_I4, 0);
g.Emit(OpCodes.Ceq);
g.Emit(OpCodes.Brtrue_S, );
var action = (Action)method.CreateDelegate(typeof(Action));
action();
Console.Read();
My questions are:
BR and BR_S, Brtrue and Brtrue_S, Brfalse and Brfalse_S and similar instructions?Thanks.
You can use a combination of the DefineLabel and
MarkLabel methods to determine the target location of the
branch. To do so, declare the labels you'll need - something like
equal and notequal. Then you can mark the spots in your IL where
the labels should be present. Once this is done, you can set the
target of your branch instruction to this label.
// Define labels
Label equal = g.DefineLabel();
Label notEqual = g.DefineLabel();
Label endOfMethod = g.DefineLabel();
// your logic here
g.Emit(OpCodes.Brtrue_S, equal);
g.MarkLabel(equal);
// some code if they are equal
g.MarkLabel(notEqual);
// some code if they are not equal
g.MarkLabel(endOfMethod); // this marks the return point
g.Emit(OpCodes.Ret);
The difference between Br, Brtrue, and Brfalse and their _S
counterparts is the length of the jump. The _S denotes short form;
the target instruction is a 1-byte signed offset from the next instruction. In the standard (non-short) form, the target is
represented by a 4-byte offset.
ILGenerator.ILOffset gives you the current offset in the IL stream, if that's what you want. You can use DefineLabel and MarkLabel, too, as goric suggested.
The only difference between brtrue.s and brtrue is that brtrue.s is the short version of brtrue. brtrue uses a 4-byte offset and brtrue.s uses a 1-byte offset. The same applies for brfalse and brfalse.s (and br/br.s).
Those are not the only short versions of an IL instruction, there are also other short instructions, like ldc.i4.0 - ldc.i4.8 for loading integers. Those are mainly useful for generating smaller binaries, but i don't think there is a big difference otherwise.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With