There was, however, one very important way in which programming in CIL was far less fun than Java Bytecode. I could not find as much good documentation, and the error messages are horrible. At least using mono (basically the open source .Net VM, while Microsoft also has one) there were essentially two errors one could get: "Unrecoverable Syntax Error" if an error happens at compile time, and "Invalid IL code" if the error happens at runtime. So, even though my code was basically correct very early (a couple of or's had to be changed to and's once I had things running...) Forgetting a single branch statement to go tho the top of a loop and a single pop instruction to clear the stack caused very hard to debug run time errors that took lots of "remove code until the error goes away" style debugging, which was not fun.
So basically, CIL is a fine stack-based assembly languages, as long as you don't cause any errors.
Also, it is worth noting that despite the title of this post...high level languages are actually quite nice. Variable names are really nice, even if I have gotten pretty good at remembering which register holds what variable.
Below code runs in 50ms on my machine.
.assembly extern mscorlib {} .assembly e79 {} .namespace E79 { .method public static void main() cil managed { .entrypoint .maxstack 100 .locals([0] int32[], [1] int32, [2] int32, [3] int32, [4] int32, [5] int32, [6] int32) ldc.i4 10 newarr int32 stloc.0 ldc.i4.0 stloc.3 ldc.i4.0 stloc.1 LOOP_INIT: ldloc.1 ldloc.0 ldlen bge OVERLOOP_INIT ldloc.0 ldloc.1 ldc.i4.0 stelem.i4 ldloc.1 ldc.i4.1 add stloc.1 br LOOP_INIT OVERLOOP_INIT: LOOP_MAIN: call string [mscorlib]System.Console::ReadLine() dup brnull OVERLOOP_MAIN call int32 [mscorlib]System.Int32::Parse(string) stloc.2 ldloc.2 ldc.i4 100 div stloc 4 ldloc.2 ldc.i4 10 div ldc.i4 10 rem stloc 5 ldloc.2 ldc.i4 10 rem stloc 6 ldloc.0 ldloc 5 ldloc.0 ldloc 5 ldelem.i4 ldc.i4.1 ldloc 4 shl or stelem.i4 ldloc.0 ldloc 6 ldloc.0 ldloc 6 ldelem.i4 ldc.i4.1 ldloc 5 shl or ldc.i4.1 ldloc 4 shl or stelem.i4 ldloc.3 ldc.i4.1 ldloc 4 shl or ldc.i4.1 ldloc 5 shl or ldc.i4.1 ldloc 6 shl or stloc.3 br LOOP_MAIN OVERLOOP_MAIN: pop ldc.i4.0 stloc 4 ldc.i4.0 stloc.1 LOOP_FINAL: ldloc.1 ldc.i4 10 bge OVERLOOP_FINAL ldloc.0 ldloc.1 ldelem.i4 ldloc.3 ldloc.1 shr ldc.i4.1 and ldc.i4.1 xor or brzero IFPART ELSEPART: ldloc.1 ldc.i4.1 add stloc.1 br LOOP_FINAL IFPART: ldloc 4 ldc.i4 10 mul ldloc.1 add stloc 4 ldc.i4.1 ldloc.1 shl not ldloc.3 and stloc.3 ldc.i4.0 stloc 5 LOOP_CLEAR: ldloc 5 ldc.i4 10 bge OVERLOOP_CLEAR ldloc.0 ldloc 5 ldloc.0 ldloc 5 ldelem.i4 ldc.i4.1 ldloc.1 shl not and stelem.i4 ldloc 5 ldc.i4.1 add stloc 5 br LOOP_CLEAR OVERLOOP_CLEAR: ldc.i4.0 stloc.1 br LOOP_FINAL OVERLOOP_FINAL: ldloc.s 4 call void [mscorlib]System.Console::WriteLine(int32) ret } }
No comments:
Post a Comment