Category Archives: Virtual Machine

News about the development of virtual machine.

First Working Assembler

I finally made the virtual-machine and XieXie Assembler working!

Here is my first XieXie test program to run in the virtual-machine (It just prints “Test” 10 times on the console):

void Main() {
    const string str1 := "Test"
    const float Math.PI := 3.141592654
    for i := 1 .. 10 {
        Print(str1)
    }
}

And here is the XieXie assembler code (currently hand-written – I’m currently just testing the assembler, not the ASM code generator):

JMP Main                ; Jump to 'Main' procedure
str1:                   ; Constant name 'str1'
DATA.string "Test\n"    ; String data field
Math.PI:                ; Constant name 'Math.PI'
DATA.float 3.141592654  ; Floating-point data field (not used here, but for testing the assembler)
Main:                   ; 'Main' procedure
XOR i0, i0              ; i0 := 0
MOV i1, 10              ; i1 := 10
.Lfor_begin:            ; Local label of 'for'-loop
PUSH str1               ; Push address of 'str1'
CALL 0x003fff21         ; SysCall 'PrintTerm(const byte* text)'
INC i0                  ; i0++
CMP i0, i1              ; Condition for next loop iteration
JL .Lfor_begin          ; Jump if comparision is 'less'
STOP                    ; Stop program execution

As you can see, I oriented myself to the x86 (or rather IA-32) assembler.
I’m using a register machine (and not a stack-machine, as Java does) with similar instructions to x86, like ‘CALL’, ‘JL’ (for ‘jump-if-less’) etc.

After assmebling, the Assembler will have generated something like this – but in byte-code and not into human readable code ;-):

JMP (PC) 4       ; Jump to 'Main' procedure with offset 4
0x54657374       ; 'T', 'e', 's', 't'
0x0a000000       ; '\n', '\0', '\0', '\0'
0x40490fdb       ; 3.141592654 represented as HEX in IEEE 754 32-bit floating-point format
XOR i0, i0
MOV i1, 10
PUSH 0x00000001  ; Push address of 'str1' at location 1
CALL 0x003fff21
INC i0
CMP i0, i1
JL (PC) -4       ; Jump if comparision is 'less' to offset -4
STOP

I also want to show you a little larger program:

void Main() {
    for row := 0 .. 9 {
        for col := 0 .. 9 {
            if row % 2 ^ col % 2 = 0 {
                PrintTerm("#")
            } else {
                PrintTerm(" ")
            }
        }
        PrintTerm("\n")
    }
}

This is the output (35 instructions, 1745 cycles):

# # # # # 
 # # # # #
# # # # # 
 # # # # #
# # # # # 
 # # # # #
# # # # # 
 # # # # #
# # # # # 
 # # # # #

And this is my hand-written XieXie assembler code:

JMP Main					; Jump to 'Main' procedure

str_chr:
DATA.string "#"
str_space:
DATA.string " "
str_nl:
DATA.string "\n"
str_pause:
DATA.string "pause"

Main:
XOR i0, i0					; row := 0
MOV i1, 10					; tmp := 10

.Lwhile1:					; while row < 10
CMP i0, i1
JGE .Lwhile1_end
	
	XOR i2, i2				; col := 0
	
	.Lwhile2:				; while col < 10
	CMP i2, i1
	JGE .Lwhile2_end
		
		PUSH i0				; (store 'row' on stack)
		PUSH i2				; (store 'col' on stack)
		
		MOD i0, 2
		MOD i2, 2
		XOR i0, i2
		XOR i2, i2
		
		CMP i0, i2			; if tmp = 0
		JNE .Lelse
		.Lif:
			
			PUSH str_chr
			CALL 0x003fff21	; PrintTerm("#")
			
		JMP .Lfi
		.Lelse:
			
			PUSH str_space
			CALL 0x003fff21	; PrintTerm(" ")
			
		.Lfi:
		
		POP i2
		POP i0
		
		INC i2				; col++
		
	JMP .Lwhile2
	.Lwhile2_end:
	
	PUSH str_nl
	CALL 0x003fff21			; PrintTerm("\n")
	
	INC i0					; row++
	
JMP .Lwhile1
.Lwhile1_end:

STOP

I’m very happy that everything works perfectly as I expected and planed it :-D

First Byte-Code Executed

I made the first (hand-written) byte-codes running inside my virtual-machine :-D.
Concurrency works pretty well, too :-)

Here are the two first test programs:

; Print(1 + 2*(3 - 4))
MOV i0, 3       ; i0 = 3
MOV i1, 4       ; i1 = 4
SUB i0, i1      ; i0 = i0 - i1
MOV i1, 2       ; i1 = 2
MUL i0, i1      ; i0 = i0 * i1
INC i0          ; i0++
CALL 0x03ffff20 ; SysCall for 'Print' (currently just for debugging)
STOP            ; Stop program execution
; int i  while i < 100 { Print(i++) }
MOV i1, 100     ; i1 = 100
XOR i0, i0      ; i0 = 0
CALL 0x03ffff20 ; SysCall for 'Print' (currently just for debugging)
INC i0          ; i0++
CMP i0, i1      ; Compare i0 with i1
JL 0x00000002   ; Jump-If-Less to address 2
STOP            ; Stop program execution