diff --git a/com/a86.asm b/com/a86.asm index 2c00ad7..c227117 100644 --- a/com/a86.asm +++ b/com/a86.asm @@ -1,88 +1,267 @@ - org 0x100 + org 0x100 - mov ax, 0x3D00 - mov dx, infile - int 0x21 - jc err + jmp init - mov [fd], ax +fcb1 equ 0x5C +eof equ 0x1A +stack equ 0x10 ; stack size - call getline +dumpax push ax + push cx + push dx + mov dx, ax + call dmpdx0 + mov al, 0x0A + call dmpdx3 + mov al, 0x0D + call dmpdx3 + pop dx + pop cx + pop ax + ret +dmpdx0 mov ah, 0xe + mov cl, 4 + ; this double-call is essentially a 4 times repeating loop + call dmpdx1 +dmpdx1: call dmpdx2 +dmpdx2: ; grab highest nibble from dx + mov al, dh + ; remove highest nibble from dx + shl dx, cl + ; shift away second-highest nibble that we accidentally copied + shr al, cl + ; map 0-9 to ascii codes for '0' to '9' + add al, 0x30 + ; if result is larger than '9', ... + cmp al, 0x3a + jl dmpdx3 + ; ... add 7 so we continue at 'A' + add al, 7 +dmpdx3: int 0x10 + ret - mov dx, [line_length] - call dumpdx +free dw 0 ; free ram size +lncnt dw 0 ; line count +rdptr dw 0xFFFF ; infile blk ptr +symbol dw 0 ; symbol of current line +offset dw 0 ; byte offset in outfile +len db 0 ; len for wrd (must be before it) +wrd dw 0,0,0,0,0,0,0,0 ; 16 byte word buf - mov si, line_buffer - mov cx, [line_length] - mov ah, 2 -l03: lodsb - mov dl, al - int 0x21 - loop l03 +getc mov bx, [rdptr] + cmp bx, 0x80 + jc l01 + mov ah, 0x14 + mov dx, fcb1 + int 0x21 + cmp al, 1 + je l02 + mov bx, 0 +l01 mov al, [0x80+bx] + cmp al, eof + je l02 + cmp al, 0 + je l02 + cmp al, 0x0A + jne l01b + inc word [lncnt] +l01b inc bx + mov [rdptr], bx + jmp l03 +l02 mov al, 0x1A +l03 cmp al, eof + ret -end: ret +;getc2 call peek +; cmp al, eof +; jne getc_ +; inc word [rdptr] +;getc_ ret -line_num: dw 1 +newlin mov dl, 0x0A + mov ah, 2 + int 0x21 + mov dl, 0x0D + int 0x21 + ret -err: mov dx, ax +error mov dl, [bx] + mov ah, 2 + int 0x21 + inc bx + cmp dl, 0x20 + jne error + mov ax, [lncnt] + call dumpax + call newlin + int 0x20 -dumpdx: ; setup bx and ah for int 10h call - xor bx, bx - mov ah, 0x0e - mov cl, 4 - ; this double-call is essentially a 4 times repeating loop - call dmpdx1 -dmpdx1: call dmpdx2 -dmpdx2: ; grab highest nibble from dx - mov al, dh - ; remove highest nibble from dx - shl dx, cl - ; shift away second-highest nibble that we accidentally copied - shr al, cl - ; map 0-9 to ascii codes for '0' to '9' - add al, 0x30 - ; if result is larger than '9', ... - cmp al, 0x3a - jl dmpdx3 - ; ... add 7 so we continue at 'A' - add al, 7 -dmpdx3: int 0x10 - ret +e_eof db "EOF " +e_dup db "DUPSYM " - ; read a character from the input file into DL -getc: mov dl, 26 - push dx - mov ah, 0x3f - mov bx, [fd] - mov cx, 1 - mov dx, sp - int 0x21 - pop dx - ret + ; scan word +scawrd mov si, wrd +l04 call getc + ; EOF is fatal + mov bx, e_eof + jz error + ; tab=end + cmp al, 9 + je pad + ; space=end + cmp al, 0x20 + je pad + ; if lbl full, continue eating + cmp si, wrd+0x10 + jnc l04 + ; insert + mov [si], al + inc si + jmp l04 + ; pad with spaces +pad mov cx, si + sub cx, wrd + mov [len], cl + cmp si, wrd+0x10 + jnc l06 + mov ah, 0x20 + xchg ah, [si] + inc si + cmp ah, 0x20 + jne pad +l06 ret -getline: mov word [line_length], 0 - mov di, line_buffer - mov cx, line_buflen -l02: push cx - call getc - pop cx - mov al, dl - cmp al, 0x0A - je l01 - cmp al, 0x0D - je l01 - cmp al, 0x1A - je l01 - inc word [line_length] - loop l02 + ; print wrd +dmpwrd mov si, wrd + mov cx, 0x10 + mov ah, 2 +l05 mov dl, [si] + cmp dl, 0x20 + je l07 + inc si + int 0x21 + loop l05 +l07 call newlin + ret -l01: ret + ; create symbol table entry + ; name is read from [wrd] + ; offset is written to [symbol] +symins cmp byte [wrd], 0x20 + je nosym + mov bx, init ; walk ptr + mov bp, [free] + add bp, bx ; end addr + jmp l09 +l08 add bx, 8 +l09 mov al, [bx] + cmp al, 0 + je l10 + call symcmp + jnz l08 + mov bx, e_dup + jmp error + ; copy str to table +l10 mov si, wrd + mov di, bx + movsw + movsw + movsw + xor ax, ax + stosw + mov byte [bx+8], 0 + mov [symbol], bx + ret -infile: db "com/a86.asm", 0 +nosym xor ax, ax + mov [symbol], ax + ret -line_buflen: equ 0x100 -line_length: dw 0 ; valid bytes in buffer -line_prefix: times 16 db " " -line_buffer: times line_buflen db 0 + ; compares 6 bytes [bx] with [wrd] + ; bit 7 of each byte is ignored +symcmp mov si, wrd + xor ax, ax + mov dx, [wrd] + xor dx, [bx] + or ax, dx + mov dx, [wrd+2] + xor dx, [bx+2] + or ax, dx + mov dx, [wrd+4] + xor dx, [bx+4] + or ax, dx + test ax, 0x8F8F + ret -fd: dw 0 + ; look up keyword in wrd + ; result is stored in bx +lookup mov ch, 0 + mov bx, s_org +l11 mov si, bx + mov di, len ; wrd immediately follows + mov cl, [bx] + test cx, cx + jz l13 + inc cl + mov dx, cx + rep cmpsb + je l12 + add bx, dx + jmp l11 + ; found! +l12 clc + ret + ; give up +l13 xor bx, bx + stc + ret + +s_org db 3, "org" +s_equ db 3, "equ" + db 0 + + ; clear symbol table +main mov byte [init], 0 + ; scan and create label +mloop call scawrd + call symins + ; scan instruction word + call scawrd + call lookup + ; special stuff + cmp bx, s_org + je iorg + mov ax, bx + call dumpax + int 0x20 + + ; org pseudo instruction +iorg mov ax, 0x5A5A + call dumpax + int 0x20 + + align 16 + + ; stuff behind here gets overwritten + ; by symbol table and program data + +init mov ax, [6] + mov dx, sp + sub dx, stack + cmp ax, dx + jc il01 + mov ax, dx +il01 sub ax, init + shr ax, 1 + and ax, 0xFFF0 + mov [free], ax + ; open input file + mov ah, 0x0F + mov dx, fcb1 + int 0x21 + mov bx, e_op + test al, al + jnz error + jmp main + +e_op db "NOFILE "