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