home comics writing pictures archive about

2016-02-13 - In IL: Variables in Visual Basic .NET

In IL

Last time we looked at how variables were defined in the IL generated by compiling a C# program. Now we will do the same with a Visual Basic .NET (VB) program and see what changes. Let’s start with a VB program that does the same thing as the C# program.

Module1.vb
Module Module1
Sub Main()
Dim b As Boolean = True
Dim c As Char = "c"c
Dim f As Single = Single.MaxValue
Dim d As Double = Double.MaxValue
Dim sb As SByte = SByte.MaxValue
Dim sh As Short = Short.MaxValue
Dim i As Integer = Integer.MaxValue
Dim l As Long = Long.MaxValue
Dim ub As Byte = Byte.MaxValue
Dim ush As UShort = UShort.MaxValue
Dim ui As UInteger = UInteger.MaxValue
Dim ul As ULong = ULong.MaxValue
Dim dl As Decimal = Decimal.MaxValue
Dim o As Object = New Object()
Dim s As String = "s"
Dim al As ArrayList = New ArrayList()
Console.WriteLine(b)
Console.WriteLine(c)
Console.WriteLine(o)
Console.WriteLine(s)
Console.WriteLine(f)
Console.WriteLine(d)
Console.WriteLine(sb)
Console.WriteLine(sh)
Console.WriteLine(i)
Console.WriteLine(l)
Console.WriteLine(ub)
Console.WriteLine(ush)
Console.WriteLine(ui)
Console.WriteLine(ul)
Console.WriteLine(dl)
Console.WriteLine(al)
End Sub
End Module
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

This program is functionally the same as the C# version. It declares a bunch of variables and then prints their string representation to the screen. There's a few syntax differences though such as how variables are declared, the lack less semicolons and curly braces, having to cast the string to a character using c. So let’s see what the compiled IL looks like.

Main
.method public static void Main() cil managed
{
.entrypoint
.custom instance void [mscorlib]System.STAThreadAttribute::.ctor() = ( 01 00 00 00 )
// Code size 240 (0xf0)
.maxstack 6
.locals init ([0] bool b,
[1] char c,
[2] float32 f,
[3] float64 d,
[4] int8 sb,
[5] int16 sh,
[6] int32 i,
[7] int64 l,
[8] uint8 ub,
[9] uint16 ush,
[10] uint32 ui,
[11] uint64 ul,
[12] valuetype [mscorlib]System.Decimal dl,
[13] object o,
[14] string s,
[15] class [mscorlib]System.Collections.ArrayList al)
IL_0000: nop
IL_0001: ldc.i4.1
IL_0002: stloc.0
IL_0003: ldc.i4.s 99
IL_0005: stloc.1
IL_0006: ldc.r4 3.4028235e+038
IL_000b: stloc.2
IL_000c: ldc.r8 1.7976931348623157e+308
IL_0015: stloc.3
IL_0016: ldc.i4.s 127
IL_0018: stloc.s sb
IL_001a: ldc.i4 0x7fff
IL_001f: stloc.s sh
IL_0021: ldc.i4 0x7fffffff
IL_0026: stloc.s i
IL_0028: ldc.i8 0x7fffffffffffffff
IL_0031: stloc.s l
IL_0033: ldc.i4 0xff
IL_0038: stloc.s ub
IL_003a: ldc.i4 0xffff
IL_003f: stloc.s ush
IL_0041: ldc.i4.m1
IL_0042: stloc.s ui
IL_0044: ldc.i4.m1
IL_0045: conv.i8
IL_0046: stloc.s ul
IL_0048: ldloca.s dl
IL_004a: ldc.i4.m1
IL_004b: ldc.i4.m1
IL_004c: ldc.i4.m1
IL_004d: ldc.i4.0
IL_004e: ldc.i4.0
IL_004f: call instance void [mscorlib]System.Decimal::.ctor(int32,
int32,
int32,
bool,
uint8)
IL_0054: newobj instance void [mscorlib]System.Object::.ctor()
IL_0059: call object [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::GetObjectValue(object)
IL_005e: stloc.s o
IL_0060: ldstr "s"
IL_0065: stloc.s s
IL_0067: newobj instance void [mscorlib]System.Collections.ArrayList::.ctor()
IL_006c: stloc.s al
IL_006e: ldloc.0
IL_006f: call void [mscorlib]System.Console::WriteLine(bool)
IL_0074: nop
IL_0075: ldloc.1
IL_0076: call void [mscorlib]System.Console::WriteLine(char)
IL_007b: nop
IL_007c: ldloc.s o
IL_007e: call object [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::GetObjectValue(object)
IL_0083: call void [mscorlib]System.Console::WriteLine(object)
IL_0088: nop
IL_0089: ldloc.s s
IL_008b: call void [mscorlib]System.Console::WriteLine(string)
IL_0090: nop
IL_0091: ldloc.2
IL_0092: call void [mscorlib]System.Console::WriteLine(float32)
IL_0097: nop
IL_0098: ldloc.3
IL_0099: call void [mscorlib]System.Console::WriteLine(float64)
IL_009e: nop
IL_009f: ldloc.s sb
IL_00a1: call void [mscorlib]System.Console::WriteLine(int32)
IL_00a6: nop
IL_00a7: ldloc.s sh
IL_00a9: call void [mscorlib]System.Console::WriteLine(int32)
IL_00ae: nop
IL_00af: ldloc.s i
IL_00b1: call void [mscorlib]System.Console::WriteLine(int32)
IL_00b6: nop
IL_00b7: ldloc.s l
IL_00b9: call void [mscorlib]System.Console::WriteLine(int64)
IL_00be: nop
IL_00bf: ldloc.s ub
IL_00c1: call void [mscorlib]System.Console::WriteLine(int32)
IL_00c6: nop
IL_00c7: ldloc.s ush
IL_00c9: call void [mscorlib]System.Console::WriteLine(int32)
IL_00ce: nop
IL_00cf: ldloc.s ui
IL_00d1: call void [mscorlib]System.Console::WriteLine(uint32)
IL_00d6: nop
IL_00d7: ldloc.s ul
IL_00d9: call void [mscorlib]System.Console::WriteLine(uint64)
IL_00de: nop
IL_00df: ldloc.s dl
IL_00e1: call void [mscorlib]System.Console::WriteLine(valuetype [mscorlib]System.Decimal)
IL_00e6: nop
IL_00e7: ldloc.s al
IL_00e9: call void [mscorlib]System.Console::WriteLine(object)
IL_00ee: nop
IL_00ef: ret
} // end of method Module1::Main
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189

That looks almost identical to the compiled C# program from last except for the added STAThreadAttribute line. But how can that be? These are two completely different programs in two completely different languages? Well it’s because they aren’t completely different programs. The actual operations being performed are identical so it makes sense that the IL generated would be the same.

IL captures the semantics of the code used to generate it not the syntax. The code to perform a specific operation could be completely different in two different languages but if those operations are meant to do the same thing then the IL generated will be similar. In the same way different languages could have features that look the same but work very differently which would generate different IL. The set of IL features is typically larger than the requirements of any single language to allow for a wide variety of language targeting the CLI.

Next time we will learn about stacks and operations.

Comments: