Import work

This commit is contained in:
Nero 2021-01-29 00:44:26 +00:00
commit d1cc870337
3 changed files with 383 additions and 0 deletions

13
Makefile Normal file
View File

@ -0,0 +1,13 @@
NASM = nasm
QEMU = qemu-system-i386
default: mon8086.bs
%.bs: %.asm
$(NASM) -o $@ $<
qemu: mon8086.bs
$(QEMU) -hda mon8086.bs
clean:
rm *.bs

73
README.md Normal file
View File

@ -0,0 +1,73 @@
A control monitor program for the Intel 8086 in a single sector (512 bytes)
Its main use it to help me debugging disk i/o and boot issues on IBM PC compatibles.
## Building
Run `make`. Requires the NASM assembler.
## How to get it running
You can run `make qemu` to make it run in qemu.
If you want to run it on a real machine, you need to write it to the boot sector first:
`dd if=mon8086.bs of=/dev/sdb1`.
## Input commands
There is no real line editing - key presses have instant effect.
- D: Dump the memory at the memory pointer. The pointer is advanced by the dumped bytes.
- E: Edit bytes at the memory pointer. You can cancel the editing by pressing space.
- S: Edit the segment of the memory pointer.
- O: Edit the offset of the memory pointer.
- R: Show the register set and next instruction bytes.
- V: This command expects a two-character argument naming the register to be changed. It allows then to edit the register value.
- G: Start execution at CS:IP address
- T: Single-step a single instruction at CS-IP
Several commands allow the user to edit a value.
While editing, pressing space results in the value being discarded.
The monitor will then return to the prompt.
This is useful for the inspection of values.
## Sample inputs
### Hexdump the bios data area
```
S 0040
O 0000
D
```
### Query drive parameters
```
E B4 08 B2 80 CD 13 CC
G
```
Replace the 80 with the bios drive number (00, 01 and 80 are common values).
The results are spread over the CX and DX registers, check Ralf Browns Interrupt List or your BIOS documentation for INT 13h/AH=8 on how to interpret the results.
### Boot arbitrary drive
```
O 7BF2
E B8 01 02 B9 01 00 BA 80 00 BB 00 7C CD 13
V IP 7BF2
G
```
Replace the 80 with the bios drive number (00, 01 and 80 are common values).
### Reboot the machine
```
V CS FFFF
V IP 0000
G
```

297
mon8086.asm Normal file
View File

@ -0,0 +1,297 @@
; monitor program that fits in a boot sector
; for debugging disk i/o and bootstrapping
%define base (0x10000 - 0x200)
org base
cpu 8086
; relocate to end of memory
init: ; 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
; set up dst addr
mov es, ax
mov di, base
; set up stack
mov ss, ax
mov sp, di
; push defptr
push ds
push si
; relocate
mov cx, 0x100
rep movsw
; reset ES for later prog
mov es, cx
; set up intr vectors
mov bx, 1*4
call .l02
; enter
mov si, 0x7C00-1
mov byte [si], 0xCC
push cs
push si
sti
retf
; call here = run proc tail twice
.l02: call .l01
.l01: mov word [bx], entry
mov word [bx+2], ss
add bx, 2*4
ret
nl: mov ax, 0x0e0A
int 0x10
mov al, 0x0D
jmp putc
space: mov al, ' '
putc: mov ah, 0x0e
int 0x10
ret
; print register set
printr: call nl
xor si, si
.l02: mov ah, 0x0e
mov al, [cs:lbls+si]
int 0x10
mov al, [cs:lbls+si+1]
int 0x10
mov al, '='
int 0x10
mov dx, [bp+si]
mov ch, ' '
call prints
add si, 2
cmp si, 24
jc .l02
les bx, [bp+18]
jmp dump
; print 16 bytes from ES:BX
dump: mov dx, es
mov ch, ':'
call prints
mov dx, bx
mov ch, ' '
call prints
push bx
mov cx, 0x10
.l01: mov dh, [es:bx]
inc bx
push cx
call printb
call space
pop cx
loop .l01
pop bx
ret
printw: call printb ; print dx
printb: call .l01 ; print dh
.l01: mov cl, 4
; 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
printn: ; map 0-9 to ascii codes for '0' to '9'
add al, 0x30
; if result is larger than '9', ...
cmp al, 0x3a
jl .noadj
; ... add 7 so we continue at 'A'
add al, 7
.noadj: mov ah, 0x0e
int 0x10
ret
; print dx and char ch
prints: call printw
mov al, ch
int 0x10
ret
getc: xor ax, ax
int 0x16
test al, al
jz getc
; to uppercase
cmp al, 0x60
jc .ret
sub al, 0x20
.ret: ret
inputw: call inputb
inputb: call inputn
inputn: jc .ret
call getc
cmp al, 0x20
stc
je .ret
sub al, 0x30
; if >9, turn 'A' to A
cmp al, 0x0A
jc .noadj
sub al, 7
.noadj: ; must be smaller than 'F'
cmp al, 0x10
jnc inputn
; append to dx
mov cl, 4
shl dx, cl
or dl, al
; print, loop & clear exit
call printn
clc
.ret: ret
; edit word at ES:BX
; space exits with carry
editw: mov dx, [es:bx]
mov ch, '.'
call prints
clc
call inputw
jc .err
mov [es:bx], dx
.err: ret
cmd_o: mov bx, di
jmp cmd_s.l01
cmd_s: lea bx, [di+2]
.l01: call editw
jmp cmd
cmd_e: les bx, [cs:di]
mov dh, [es:bx]
call printb
mov al, '.'
int 0x10
mov cx, 2
clc
call inputb
jc cmd
mov [es:bx], dl
inc word [cs:di]
call space
jmp cmd_e
entry: push es
push ds
push di
push si
push bp
push bx
push dx
push cx
push ax
mov bp, sp
cmd_r: call printr
cmd: ; display prompt
call nl
mov al, '-'
call putc
.l01: call getc
cmp al, 0x41
jc .l01
; process input char
call putc
push ax
call space
pop ax
; set up default for cmds
mov dx, cs
mov ds, dx
mov es, dx
mov di, defptr
; show and edit mem
cmp al, 'D'
je cmd_d
cmp al, 'E'
je cmd_e
; show and edit regs
cmp al, 'R'
je cmd_r
cmp al, 'V'
je cmd_v
; actions
cmp al, 'G'
je cmd_g
cmp al, 'T'
je cmd_t
; set working ptr
cmp al, 'S'
je cmd_s
cmp al, 'O'
je cmd_o
err: mov al, '?'
call putc
jmp cmd
cmd_d: les bx, [di]
mov cx, 8
.l01: push cx
call nl
call dump
pop cx
add bx, 0x10
mov [cs:di], bx
loop .l01
jmp cmd
cmd_v: call regn
mov ax, dx
mov di, lbls
mov cx, 11
repne scasw
jne err
sub di, lbls+2
lea bx, [bp+di]
call space
call editw
jmp cmd
regn: call .l01
xchg dh, dl
.l01: call getc
call putc
mov dh, al
ret
cmd_t: or byte [bp+23], 1
jmp exit
cmd_g: and byte [bp+23], 0xFE
exit: pop ax
pop cx
pop dx
pop bx
pop bp
pop si
pop di
pop ds
pop es
iret
; names for registers
lbls: db "AXCXDXBXBPSIDI" ; gpr
db "DSES" ; seg regs
db "IPCSFL" ; iret frmae
defptr: equ (base-4)
times 510-($-$$) db 0x00
db 0x55,0xaa