Branching

The branch instruction is available in various permutations, but in all circumstances it is essentially a goto. The target of a branch instruction is a label. Most branch instructions are conditional and based on a Boolean condition. For an unconditional goto, use the br instruction. Loop and other transfer-of-control statements in C# are implemented with some combination of branch instructions.

A conditional branch can be made with the brtrue and brfalse statements. The brtrue instruction branches on a true condition, whereas the brfalse branches on a false condition. These instructions consume a Boolean value, which must be placed on the evaluation stack prior to the statements.

Comparison instructions perform a comparison of the top two values of the evaluation stack. The two values are replaced on the evaluation stack with the result of the comparison, which is either true or false. The comparison should be between related types.

Table 14-4 lists the comparison instructions. In the table, assume that t2 is the top value on the evaluation stack, t1 is the next value (t2 is the last item placed on the evaluation stack and the next to be removed).

Table 14-4. Comparison instructions

Instruction

Comparison

ceq

t1 equal to t2

cgt

t1 greater than t2

clt

t1 less than t2

cgt.un and clt.un

Unsigned or unordered version of the comparison operations

This sample code shows unconditional and conditional branching. It also contains an example of a comparison instruction:

.assembly extern mscorlib {}
.assembly application {}

.namespace Donis.CSharpBook {

    .class Starter {

        .method static public void Main() il managed {
            .entrypoint
            ldc.i4.3
            ldc.i4.1
            cgt
            brtrue greater
            ldstr "{0} is less than or equal to {1}"
            br end
greater:    ldstr "{0} is greater than {1}"
end:        ldc.i4.3
            box int32
            ldc.i4.1
            box int32
            call void [mscorlib] System.Console::WriteLine(
                string, object, object)
            ret
        }
    }
}

As a convenience, branch and comparison instructions are combinable. The combined instruction compares the top two values of the evaluation stack and branches on the result. These are called comparative branching instructions. Instead of requiring two instructions to perform the test, only one instruction is needed.

Table 14-5 lists comparative branching instructions.

Table 14-5. Comparative branching instructions

Instruction

Description

beq

Branch on equal

bne

Branch on not equal

bge

Branch on greater than or equal

bgt

Branch on greater than

ble

Branch on less than or equal

blt

Branch on less than

bgt.un, blt.un, and bne.un

The unsigned version of these instructions

Here is an example of a for loop in MSIL code. The loop increments the count from zero to five. The current count is displayed to the console in iterations of the loop. The sample code uses the short form of the branch instruction. As with all short-form instructions, the operand is limited to a single byte. The short form of branch instructions cannot jump to a label that is more than a one-byte offset from the beginning of the next instruction. If the branch offset is greater than one byte, ILASM generates a compiler error:

.assembly extern mscorlib {}
.assembly application {}

.namespace Donis.CSharpBook {

    .class Starter {

        .method static public void Main() il managed {
            .entrypoint
            .locals (int32 count)
            ldc.i4.0
            stloc.0
            br.s loop
for:        ldloc count
            ldc.i4.1
            add
            dup
            stloc count
            call void [mscorlib] System.Console::WriteLine(int32)
loop:       ldloc count
            ldc.i4.5
            clt
            brtrue.s for
            ret
        }
    }
}

Calling Methods

There are many ways to call methods. So far in this chapter, only the call and callvirt instructions have been shown in the sample code. Some instructions or actions, such as newobj, call a method implicitly. The newobj instruction calls a constructor, whereas the static constructor is called implicitly on the first access to the class or object.

The call instructions have the same general syntax:

callsuffix returntype [assembly] signature

The value of the returntype is placed on the evaluation stack by the method; assembly is the location of the method. If the method is in the current assembly, the assembly element can be omitted. The complete signature of the method is represented by signature.

This section lists the call instructions in MSIL.

call

The call instruction is intended for calling nonvirtual methods. The call instruction can be used with a virtual method. In this circumstance, the virtual method is called as a normal method, which is based on the class in which the method is declared rather than on the derived instance.

callvirt

The callvirt instruction calls a virtual method. For nonvirtual methods, a nonvirtual call is conducted.

calli

The calli instruction calls a function indirectly through a function pointer. Place each function parameter and then the function pointer on the evaluation stack. The calli syntax is slightly different from other call instructions. It does not include the target assembly or method name in the syntax, but it does include the return type and the signature other than the name. Use the ldftn instruction to place a function pointer for a particular method on the stack.

This sample code shows both the calli and ldftn instructions:

.assembly extern mscorlib {}
.assembly application {}

.namespace Donis.CSharpBook {

    .class Starter {

        .method static public void Main() il managed {
            .entrypoint
            ldstr "Donis"
            ldftn void  Donis.CSharpBook.Starter::Name(string)
            calli void(string)
            ret
        }
        .method static public void Name(string)
                il managed {
            ldstr "Hello, {0}!"
            ldarg.0
            call void [mscorlib] System.Console::WriteLine(string, object)
            ret
        }
    }
}

jmp

The jmp instruction jumps from the current method to the target method and transfers the arguments. The caller and callee must have matching signatures, and the evaluation stack for the current method must be empty. The code after the jmp site in the calling function is abandoned.

Here is sample code of the jmp instruction:

.assembly extern mscorlib {}
.assembly application {}
.namespace Donis.CSharpBook {
    .class Starter {
        .method static public void Main() il managed {
            .entrypoint
            ldstr "Aloha!"
            call void Donis.CSharpBook.Starter::MethodA(string)
            ret
        }
        .method static public void MethodA(string) il managed {
            ldstr "Before jump"
            call void [mscorlib] System.Console::WriteLine(string)
            ldstr "In MethodA: {0}"
            ldarg.0
            call void [mscorlib] System.Console::WriteLine(string, object)
            jmp void Donis.CSharpBook.Starter::MethodB(string)
            ldstr "After jump"
            call void [mscorlib] System.Console::WriteLine(string)
            ret
        }
        .method static public void  MethodB(string) il managed {
            ldstr "In MethodB: {0}"
            ldarg.0
            call void [mscorlib] System.Console::WriteLine(string, object)
            ret
        }
    }
}

This program jumps from MethodA to MethodB. In MethodA, the instructions after the jmp instruction are orphaned. Therefore, the message "After jump" is not displayed. MethodB returns directly to Main, not MethodA.

tail

The tail instruction is a prefix instruction and similar to the jmp instruction. However, the arguments must be loaded explicitly on the evaluation stack and the method signatures can be different. Otherwise, the functions are operationally equivalent.

Here is the syntax of the tail instruction:

tail callsuffix returntype [assembly] signature
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.189.195.34