diff --git a/boot/ihex.asm b/boot/ihex.asm new file mode 100644 index 0000000..6fdb5f9 --- /dev/null +++ b/boot/ihex.asm @@ -0,0 +1,219 @@ +; ihex - bootsector that reads intel hex from the keyboard + +%define base (0x10000 - 0x400) + + org base + + ; relocate to end of memory +reloc: ; set up src addr + xor ax, ax + mov ds, ax + mov si, 0x7C00 + ; calculate target segment + mov ax, [0x413] + mov cl, 6 + shl ax, cl + sub ax, 0x1000 + mov es, ax + mov di, base + ; set up dst addr + mov ss, ax + mov sp, di + ; relocate + mov cx, 0x100 + rep movsw + ; set DS + mov ds, ax + ; jump relocated + push ds + mov ax, main + push ax + retf + + ; AL -> display +putc: mov ah, 0x0e + xor bx, bx + int 0x10 + ret + + ; read a line +read: mov si, line +.loop: xor ax, ax + int 0x16 + cmp al, 0x08 + je .bs + cmp al, 0x0A + je .cr + cmp al, 0x0D + je .cr + cmp ax, 0x4D00 + je .r + test al, al + jz .loop + cmp al, 0x60 + jc .l01 + sub al, 0x20 +.l01: mov [si], al +.l02: inc si + call putc + jmp .loop +.r: mov al, [si] + jmp .l02 +.bs: dec si + push ax + call putc + mov al, 0x20 + call putc + pop ax + call putc + jmp .loop +.cr: mov cx, line + xchg cx, si + sub cx, si + jmp nl + + ; read 2 hex chars from line into al + ; BX is byte number +getb: add bx, bx + lea si, [line+1+bx] + mov ax, [si] + call .a2b + xchg ah, al + call .a2b + test ax, 0xF0F0 + jnz err + push cx + mov cl, 4 + shl al, cl + shr ax, cl + pop cx +.ret: ret +.err: xor ax, ax + stc + ret +.a2b: sub al, 0x30 + cmp al, 0x10 + jc .ret + sub al, 7 + ret + + ; same like getb, except reads a full word +getw: push bx + call getb + mov dl, al + pop bx + inc bx + call getb + mov ah, dl + ret + +nl: mov al, 0x0A + call putc + mov al, 0x0D + jmp putc + +main: mov sp, base ; reset stack + call read + cmp byte [line], ':' + jmp hexcmd + +err: mov cx, si + sub cx, line + jz .l01 + cmp cx, 80 + jnc .l01 + mov al, ' ' +.l02: call putc + loop .l02 +.l01: mov al, '^' + call putc + mov al, 7 + call putc + call nl + jmp main + +hexcmd: sub cx, 11 + jc err + shr cx, 1 + xor bx, bx + call getb + ; line not long enough for size field + cmp cl, al + jc err + ; calculate checksum + add cl, 5 + xor dx, dx +.loop: push bx + call getb + pop bx + add dl, al + inc bx + add dl, al + loop .loop + jnz err + ; get record type + mov bx, 3 + call getb + cmp al, 0 + je cmd0 + cmp al, 1 + je cmd1 + cmp al, 2 + je cmd2 + cmp al, 3 + je cmd3 + jmp err + + ; ihex command 0: data +cmd0: les di, [addr] + mov bx, 0 + push bx + call getb + pop bx + mov cx, ax + add bx, 4 +.loop: push bx + call getb + pop bx + inc bx + stosb + loop .loop + mov [addr], di + jmp main + + ; ihex command 1: eof / exec +cmd1: push word [exec+2] + push word [exec] + push es + pop ds + retf + + ; ihex command 2: set segment +cmd2: mov bx, 4 + call getw + mov [addr], ax + jmp main + + ; ihex command 3: set start address +cmd3: ; copy CS + mov bx, 4 + call getw + mov [exec+2], ax + ; copy IP + mov bx, 6 + call getw + mov [exec], ax + jmp main + +hlt: hlt + jmp hlt + +addr: dw 0, 0x100 +exec: dw 0, 0x100 + + times 510-($-$$) db 0x00 + db 0x55,0xaa + +section .bss + +line: resb 80