org 7C00h

start:
  jmp main	  ; jump to start of bootloader

SetCursorLocation:
	mov	ah,2
	mov	bh,0
	int	10h
	ret
PrintEax2HexString:
; IN: cl=eax length in nibbles (bytes*2)
;     eax=number to convert
;        push    ebx
	push	cx
	neg	cx
;        lea     cx,[ecx*4+32+4] ;we only need cl not the full ecx
	shl	cx,2
	add	cx,32+4
	mov	ebx,eax
	rol	ebx,cl;4+32-4*6 ;(cl=6)
	pop	cx
      .loop:
	mov	eax,ebx
	rol	ebx,4
	and	eax,1111b
	add	al,30h
	cmp	al,3Ah
	jc	@f
	add	al,7
      @@:
	mov	ah,0Eh
	int	10h
	dec	cl
	jnz	.loop
;        pop     ebx
	mov	ax,0E20h
	int	10h
ret
KeyboardFunctions:
      .get_another:
	mov	cx,[cs:MemAdr]
	mov	dx,[cs:CurPos]
	mov	ah,0
	int	16h
	cmp	al,'x'
	je	.Execute
	test	al,al
	je	.command
	cmp	al,30h
	jc	.get_another
	call	EditCharacter
	jc	.get_another
	mov	ah,0
	int	16h
	test	al,al
	je	.command
	cmp	al,30h
	jc	.get_another
	call	EditCharacter
	jc	.get_another
	shl	bl,4
	shr	bx,4
	mov	[ecx],bl
	add	dl,3
	inc	cx
	ret
      .command:
	mov	al,ah
	cmp	al,48h
	je	.Up
	cmp	al,49h
	je	.PageUp
	cmp	al,4Bh
	je	.Left
	cmp	al,4Dh
	je	.Right
	cmp	al,4Fh
	je	.End
	cmp	al,50h
	je	.Down
	cmp	al,51h
	je	.PageDown
	ret
;      .Esc:
;        cli
;        hlt
;        ret
      .Up:
	sub	cx,10h
	dec	dh
	ret
      .PageUp:
	sub	cx,100h
	ret
      .Left:
	dec	cx
	sub	dl,3
	ret
      .Right:
	inc	cx
	add	dl,3
	ret
      .End:
	push	ds
	add	word[esp],1000h
	pop	ds
	ret
      .Down:
	add	cx,10h
	inc	dh
	ret
      .PageDown:
	add	cx,100h
	ret
      .Execute:
	jmp	[MemAdr]
EditCharacter:
	mov	ah,0Eh
	cmp	al,3Ah
	jnc	.isitA_F
	; NUMBER: 0..9
	shl	bx,8
	mov	bl,al
	sub	bl,30h
	jmp	.yes
      .isitA_F:
	shl	bx,8
	and	al,not 20h
	mov	bl,al
	sub	bl,40h-9
	cmp	bl,16
	jnc	.no
	; HEX: A..F
      .yes:
	int	10h
	clc
	ret
      .no:
	stc
	ret
;*********************************************
;       Bootloader Entry Point
;*********************************************
main:
	mov	ax,3
	int	10h
      .running:
	mov	si,[cs:MemAdr]
	and	si,not 255
	mov	dx,0107h
	call	SetCursorLocation
;        jmp     .print_2
      .print:
	test	si,1111b
	jnz	.not16aligned
	mov	ax,0E0Dh
	int	10h
	mov	al,0Ah
	int	10h
	mov	ax,ds
	shl	eax,4
	or	eax,esi
	mov	cl,6
	call	PrintEax2HexString
      .not16aligned:
	lodsb
	mov	cl,2
	call	PrintEax2HexString

	test	si,1111b
	jnz	.not16aligned_2
	mov	ecx,-16
	mov	bx,0E2Eh
	mov	ax,bx
      .string:
	mov	al,[esi+ecx]
	cmp	al,20h
	cmovc	ax,bx
	int	10h
      .not_printable:
	inc	ecx ;must be 32 bits, then ecx will wrap to 0
	jne	.string
      .print_2:
      .not16aligned_2:

	test	si,0FFh
	jnz	.print
	mov	dx,[cs:CurPos]
	call	SetCursorLocation

	call	KeyboardFunctions
	mov	[cs:MemAdr],cx
	cmp	dl,7
	jnc	@f
	mov	dl,52
	dec	dh
      @@:
	cmp	dh,2
	jnc	@f
	mov	dh,17
      @@:
	cmp	dl,52
	jbe	@f
	mov	dl,7
	inc	dh
      @@:
	cmp	dh,17
	jbe	@f
	mov	dh,2
      @@:
	mov	[cs:CurPos],dx
	jmp	.running
;        int     0x19                                ; warm boot computer
  MemAdr dw 7C00h
  CurPos dw 0207h
  times 510-($-$$) DB 0
  dw 0xAA55