Hello, java!

I was messing around with Java bytecode today for no particular reason. It’s a fairly simple assembly language — stack based so it takes a little getting used to but not hard for anyone who has used an HP calculator. I installed a copy of jasmin from my apt repository and got to work.

I wanted to make a “Hello, world!” that wasn’t completely obvious at first blush, so the plan of attack was to just push all the ascii codes on the stack in reverse order then call System.out.print() on them in a loop. Each iteration checks the loop count, if ok then pop the next code and print it. Here is where the bytecode verifier is a pain in the ass: apparently, the instructions must be executed each time through a loop with the same stacksize, or else you are branded an evil hacker. Very annoying. I could’ve used an array instead but that also takes a bunch of pushes and stores, so I just unrolled the loop. It works, I guess. Code after the jump.

.class Xyz
.super java/lang/Object

.method public static zyx(C)V
.limit stack 2
getstatic java/lang/System/out Ljava/io/PrintStream;
iload 0
invokevirtual java/io/PrintStream/print(C)V
return
.end method

.method public static main([Ljava/lang/String;)V
.limit stack 14
bipush 10
bipush 0x21
bipush 100 
bipush 0x6c 
bipush 114 
dup
bipush -3
iadd
bipush 0x77 
bipush 32  
bipush 44
bipush 0x6f 
bipush 108 
dup
bipush 101 
bipush 72
invokestatic Xyz/zyx(C)V
invokestatic Xyz/zyx(C)V
invokestatic Xyz/zyx(C)V
invokestatic Xyz/zyx(C)V
invokestatic Xyz/zyx(C)V
invokestatic Xyz/zyx(C)V
invokestatic Xyz/zyx(C)V
invokestatic Xyz/zyx(C)V
invokestatic Xyz/zyx(C)V
invokestatic Xyz/zyx(C)V
invokestatic Xyz/zyx(C)V
invokestatic Xyz/zyx(C)V
invokestatic Xyz/zyx(C)V
invokestatic Xyz/zyx(C)V
return
.end method