anattos/anattos.asm

389 lines
4.4 KiB
NASM

; CC0 2021 nortti
org 0x7c00
jmp 0:start
start:
cld
cli
xor dx, dx
mov ds, dx
mov ss, dx
mov sp, $$
sti
; VGA video memory
mov ax, 0xb800
mov es, ax
; Start at bootloader
mov bx, $$
init_screen:
; Set 80x25 text mode
mov ax, 3
int 0x10
; Clear screen
xor di, di
xor ax, ax
mov cx, 80 * 25
rep stosw
mainloop:
; Align dump display to 256 byte page
mov si, 0xff00
and si, bx
; Display RAM contents
xor di, di
mov bp, 256
.dump:
cmp si, bx
jne .not_cursor
; Set cursor
pusha
shr di, 1 ; Cursor position is in char cells
mov dx, 0x3d4
mov al, 0x0f ; Lower 8 bits of position
out dx, al
inc dx
mov ax, di
out dx, al
mov dx, 0x3d4
mov al, 0x0e ; Higher 8 bits of position
out dx, al
inc dx
mov ax, di
mov al, ah
out dx, al
popa
.not_cursor:
lodsb
call hexprint8
; Fletcher-16
add dl, al
adc dl, 0
add dh, dl
adc dh, 0
inc di
inc di
dec bp
test bp, 0x0f
jnz .dump
inc di
inc di
mov ax, dx
call hexprint16
xor dx, dx
add di, (80 - 16*3 - 5)*2
test bp, bp
jnz .dump
.end_dump:
; Display address
mov di, 17 * 80 * 2
mov ax, bx
call hexprint16
xor ax, ax
call disasm
; Read user input
int 0x16
.left:
cmp ah, 0x4b
jne .right
dec bx
.right:
cmp ah, 0x4d
jne .up
inc bx
.up:
cmp ah, 0x48
jne .down
sub bx, 16
.down:
cmp ah, 0x50
jne .digit09
add bx, 16
.digit09:
cmp al, '0'
jb .digitaf
cmp al, '9'
ja .digitaf
sub al, '0'
jmp digit
.digitaf:
cmp al, 'a'
jb .r
cmp al, 'f'
ja .r
sub al, 'a' - 10
jmp digit
.r:
cmp al, 'r'
mov al, 0xff
jne digit.update_nybble
pusha
call bx
popa
jmp init_screen
digit:
; 00 … 0f are stored nybbles, other values are sentinels
test byte [high_nybble], 0xf0
jnz .update_nybble
mov cl, [high_nybble]
shl cl, 4
or al, cl
mov [bx], al
inc bx
mov al, 0xff
.update_nybble:
mov [high_nybble], al
jmp mainloop
; IN:
; ah = 0
; bx = offset
disasm:
pusha
mov si, bx
mov di, 19 * 80 * 2
mov cx, 2 * 80
push di
rep stosw
pop di
; Opcode byte
lodsb
mov dl, al
shr al, 1
cmp al, 0x7f ; fe ff
jz .do_disasm
test al, 0x62 ; add, or, adc, sbb, and, sub, xor, cmp
jz .do_disasm
cmp al, 0x40
jb .no_disasm
cmp al, 0x45 ; 80 81 82 83, test, mov
jbe .do_disasm
cmp al, 0x60 ; c0 c1
je .do_disasm
jb .no_disasm
cmp al, 0x62 ; c4 c5
je .do_disasm
test al, 0x16 ; d0 d1 d2 d3
jnz .no_disasm
.do_disasm:
; Opcode
shr al, 1
call hexprint8
inc di
inc di
; Direction / extend
mov ax, 0x0700 + ' '
test dl, 2
jz .print_direction
mov al, 's'
.print_direction:
stosw
inc di
inc di
; Width
mov al, 'b'
test dl, 1
jz .print_width
mov al, 'w'
.print_width:
stosw
add di, (80 - 6) * 2
; Mod-reg-r/m byte
lodsb
mov dh, al
; Mode
shr al, 6
call hexprint4
inc di
inc di
; Reg or opcode extension
mov al, 0x38
and al, dh
shr al, 3
cmp dl, 0x80
jb .not_op_ext
cmp dl, 0x83 ; 80 81 82 83
jbe .op_ext
cmp dl, 0x8b ; test mov
jbe .not_op_ext
.op_ext:
call hexprint4
jmp .skip_print_reg
.not_op_ext:
call .reg
.skip_print_reg:
inc di
inc di
; R/m
mov al, 0x07
and al, dh
cmp dh, 0xc0 ; Hacky way to check if top two bits are both set
jb .base
call .reg
.no_disasm:
popa
ret
.reg:
xor bx, bx
mov bl, al
test dl, 1
jz .reg8
mov al, byte [bx + register_first]
stosw
shr bx, 1
mov al, byte [bx + register_second]
stosw
ret
.reg8:
mov cl, al
shr cl, 2
and bl, 3
mov al, byte [bx + register_first]
stosw
mov bl, cl
mov al, byte [bx + register_halves]
stosw
ret
.base:
mov cl, al
test al, 4
jnz .base47
mov al, 'b'
stosw
mov bx, 2
and bl, cl
shr bl, 1
mov al, byte [bx + base_first]
stosw
mov al, '+'
stosw
.si_di:
mov bl, 1
and bl, cl
mov al, byte [bx + base_second]
stosw
mov al, 'i'
stosw
popa
ret
.base47:
test al, 2
jz .si_di
mov al, 'b'
stosw
mov bx, 7
sub bl, cl
mov al, byte [bx + base_first]
stosw
popa
ret
register_first db 'acdbsb'
base_second db 'sd'
register_second db 'x'
base_first db 'xp'
db 'i'
register_halves db 'lh'
; IN: ax/al/al = number
; UPDATE: di = index into video memory
hexprint16:
xchg al, ah
call hexprint8
xchg al, ah
hexprint8:
rol al, 4
call hexprint4
rol al, 4
hexprint4:
push ax
and al, 0xf
cmp al, 10
jb .below_10
add al, 'a' - '0' - 10
.below_10:
add al, '0'
; 07 = white on black
mov ah, 0x07
stosw
pop ax
ret
times 510 - ($ - $$) db 0
high_nybble db 0x55, 0xaa