13

I was studying about the Intermediate Language for C#(IL) and came across the following piece of code:-

//Add.il
//Add Two Numbers

.assembly extern mscorlib {}

.assembly Add
{
     .ver 1:0:1:0
}
.module add.exe

.method static void main() cil managed
{
    .maxstack 2
    .entrypoint

    ldstr "The sum of 50 and 30 is = "
    call void [mscorlib]System.Console::Write (string)

    ldc.i4.s 50
    ldc.i4 30    
    add
    call void [mscorlib]System.Console::Write (int32)
    ret
}

I am a beginner in understanding IL but I know the meaning of these very basic instructions used in the Main, in the above example.

My question is that Is there any difference between the instructions ldc.i4.s which is used to load 50 and the instruction ldc.i4 which is used to load 30 onto the evaluation stack.

How does the compiler decide which instruction to use(out of these two) and when?

svick
  • 236,525
  • 50
  • 385
  • 514
Pratik Singhal
  • 6,283
  • 10
  • 55
  • 97
  • I was about to ask a question about ldc.i4.s and came across your post while checking possible duplicates. In my case, emitting this op code adds 3 Nop instructions to the generated IL. I wonder if it is the same there too. But I see that the compiler can use this instruction without the Nop instructions added. That is because even i4.s expects a 4 byte integer and since you give it a byte, it fills the remaining three slots with Nop, and this is documented as well – Oguz Ozgul Dec 08 '15 at 19:47

4 Answers4

11

For signed byte values, no.

ldc.i4.s is a more efficient encoding for pushing the integers from -128 to 127 onto the evaluation stack.

See MSDN

leppie
  • 115,091
  • 17
  • 196
  • 297
4

You can ldc.i4.s when your value is between -128 to 127.

ldc.i4.s is a more efficient encoding for pushing the integers from -128 to 127 onto the evaluation stack.

Twenty
  • 5,234
  • 4
  • 32
  • 67
3

The difference is that ldc.i4.s can only be used when the operand can fit in a signed byte (-128 to 127 inclusive). The benefit is that the resulting IL is shorter, saving space in the program. This is helpful because many constant loads use small constants.

Doug McClean
  • 14,265
  • 6
  • 48
  • 70
1

ldc.i4.s

Push num of type int32 onto the stack as int32. Push -1 of type int32 onto the stack as int32 (alias for ldc.i4.m1). Push num onto the stack as int32, short form. Push num of type int64 onto the stack as int64.

OpCode : 0x1F

Instruction: ldc.i4.s

Description: Push num onto the stack as int32, short form.

ldc.i4

Push -1 of type int32 onto the stack as int32 (alias for ldc.i4.m1). Push num onto the stack as int32, short form. Push num of type int64 onto the stack as int64. Push num of type float32 onto the stack as F.

OpCode : 0x20

Instruction: ldc.i4

Description: Push num of type int32 onto the stack as int32. Base instruction

Amarnath Balasubramanian
  • 9,300
  • 8
  • 34
  • 62