%include "lib/lib.h"

extern putc, puts, exit

SECTION .data
openerrstr: db `Unable to open file for reading\n`, 0
    digits: db "0123456789ABCDEF", 0
    offset: dq 0

SECTION .bss
    num: resb 1
     fd: resq 1
      r: resq 1
    buf: resb 16
  
SECTION .text

printbyte:
	mov	dl,BYTE [num]
	shr	dl, 4
	and	dl, 0xF
	mov	al, BYTE [digits + rdx]
	call	putc

	mov	dl, BYTE [num]
	and	dl, 0xF
	mov	al, BYTE [digits + rdx]
	call	putc
	ret

printoffset:
	mov	rax, QWORD[offset]
	shr	rax, 24
	and	rax, 0xFF
	mov	BYTE [num], al
	call	printbyte

	mov	rax, QWORD[offset]
	shr	rax, 16
	and	rax, 0xFF
	mov	BYTE [num], al
	call	printbyte

	mov	rax, QWORD[offset]
	shr	rax, 8
	and	rax, 0xFF
	mov	BYTE [num], al
	call	printbyte

	mov	rax, QWORD[offset]
	and	rax, 0xFF
	mov	BYTE [num], al
	call	printbyte
	ret

global _start
_start:
	mov	QWORD [fd], STDIN_FILENO	; int fd = STDIN_FILENO;
  
	cmp	QWORD [rsp], 1			; if (argc > 1) {
	jle	.mainloop

	mov	rax, SYS_OPEN
	mov	rdi, [rsp+16]
	mov	rsi, O_RDONLY
	syscall
	mov	QWORD[fd], rax			;    fd = open(argv[1], O_RDONLY);
	cmp	rax, 0				;    if (fd < 0) {
	jge	.mainloop

	mov	rsi, openerrstr
	call	puts				;      putstr("Unable to open file for reading\n");
	mov	rdi, 1
	call	exit				;      return 1;

.mainloop:
	mov	rax, SYS_READ
	mov	rdi, QWORD [fd]
	mov	rsi, buf
	mov	rdx, 16
	syscall
	mov	QWORD[r], rax
	cmp	rax, 0
	jle	.mainloop_done			;  while ((r = read(fd, buf, 16)) > 0) {

	call	printoffset			;    printoffset(offset);

	mov	al, ':'
	call	putc				;    putcha(':');

	mov	r15, 0				;    r15 = 0;
.iloop1:
	cmp	r15, QWORD[r]			;    while(r15 < r) {
	jge	.iloop1_done
	
	mov	al, ' '
	call	putc				;      putcha(' ');

	cmp	r15, 8
	jne	.endif1				; if (r15 == 8) putcha(' ');
	mov	al, ' '
	call	putc

.endif1:
	mov	al, BYTE [buf + r15]
	mov	BYTE [num], al
	call	printbyte			;      printbyte(buf[r15]);

	inc	r15				;      r15++;

	jmp	.iloop1
.iloop1_done:

.iloop2:
	cmp	r15, 16				;    while(r15 < 16) {
	jge	.iloop2_done

	mov	al, ' '
	call	putc				;      putcha(' ');

	cmp	r15, 8
	jne	.skip				;      if (r15 == 8)
	mov	al, ' '
	call	putc				;          putcha(' ');

.skip:
	mov	al, ' '
	call	putc				;      putcha(' ');
	mov	al, ' '
	call	putc				;      putcha(' ');

	inc	r15				;      r15++;

	jmp	.iloop2				;    }

.iloop2_done:

	mov	al, ' '
	call	putc				;    putcha(' ');
	mov	al, ':'
	call	putc				;    putcha(':');
	mov	al, ' '
	call	putc				;    putcha(' ');
	
	mov	r15, 0				;    r15 = 0;

.iloop3:
	cmp	r15, QWORD[r]
	jge	.iloop3_done			;    while(r15 < r) {
	
	mov	al, BYTE [buf + r15]
	cmp	al, 32
	jl	.dot
	cmp	al, 126
	jg	.dot				;      if (buf[r15] >= 32 && buf[r15] <= 126) putcha(buf[r15]);
	call	putc
	jmp	.skipdot
.dot:
	mov	al, '.'				;      else putcha(' ');
	call	putc

.skipdot:
	inc	r15				;      r15++;

	jmp	.iloop3				;    }
.iloop3_done:

	mov	al, `\n`
	call	putc				;    putcha('\n');
	add	r14, QWORD[r]
	add	QWORD[offset], r14		;    offset += r;

	jmp	.mainloop				;  }
.mainloop_done:

	mov	rdi, 0
	call	exit				;  return 0;
