Task

Implement a    HQ9+    interpreter or compiler.




 
 
;ds:si: pointer to asciiz string containing HQ9++ source code
ExecuteHQ9:
	push ax
	push dx
	push si
	push di
	push es
	push bx
	mov bx, si
	.interpret:
		lodsb
		cmp al, 'H'
		je .doHelloWorld
		cmp al, 'Q'
		je .doPrintCode
		cmp al, '9'
		je .doDrinkBeer
		cmp al, '+'
		je .doCounter
		pop bx
		pop es
		pop di
		pop si
		pop dx
		pop ax
		ret
 
	.doHelloWorld:
		push ds
		mov ax, cs
		mov ds, ax
		push si
		mov si, .dataHelloWorld
		call .printString
		pop si
		pop ds
		jmp .interpret
 
	.doPrintCode:
		push si
		mov si, bx
		call .printString
		pop si
		jmp .interpret
 
	.doDrinkBeer:
		push ds
		push si
		push ax
		mov ax, cs
		mov ds, ax
		mov ax, 99
		.beer_loop:
			call .printHexNumber
			mov si, .dataBeerSong1
			call .printString
			call .printHexNumber
			mov si, .dataBeerSong2
			call .printString
			dec ax
			call .printHexNumber
			mov si, .dataBeerSong3
			call .printString
			test ax, ax
			jnz .beer_loop
		pop ax
		pop si
		pop ds
		jmp .interpret
 
	.doCounter:
		push ax
		inc ax
		pop ax
		jmp .interpret
 
	.printString:
		push ax
		push si
	 .looping:
		lodsb
		test al, al
		jz .done
		mov ah, 0Eh
		int 10h
		jmp .looping
	 .done:
		pop si
		pop ax
		ret
 
	.printHexNumber:
			pusha
			push ds
			mov ax, cs
			mov ds, ax
			push word 0
			mov bx, ax
			xor dx, dx
			mov cx, 4r
	 .convert_loop:
			mov ax, bx
			and ax, 0Fh
			cmp ax, 9
			ja  .greater_than_9
			add ax, '0'
			jmp .converted
	 .greater_than_9:
			add ax, 'A'-0Ah
	 .converted:
			push ax
			shr bx, 4
			dec cx
			jnz .convert_loop
	 .popoff:
			pop ax
			cmp ax, 0
			je .done
			mov ah, 0Eh
			int 10h
			jmp .popoff
		.done:
			pop ds
			popa
			ret
 
	.dataHelloWorld: db "Hello World!", 0
	.dataBeerSong1: db " bottles of beer on the wall ", 0
	.dataBeerSong2: db " bottles of beer", 13, 10, "Take one down, pass it around "
	.dataBeerSong3: db 0, " bottles of beer on the wall", 0
 
 