Compare commits
3 Commits
6365bd73a0
...
782ff93ace
Author | SHA1 | Date | |
---|---|---|---|
782ff93ace | |||
390fedc848 | |||
c7ee622847 |
451
asm_files/list-0042.asm
Normal file
451
asm_files/list-0042.asm
Normal file
@ -0,0 +1,451 @@
|
|||||||
|
; ========================================================================
|
||||||
|
;
|
||||||
|
; (C) Copyright 2023 by Molly Rocket, Inc., All Rights Reserved.
|
||||||
|
;
|
||||||
|
; This software is provided 'as-is', without any express or implied
|
||||||
|
; warranty. In no event will the authors be held liable for any damages
|
||||||
|
; arising from the use of this software.
|
||||||
|
;
|
||||||
|
; Please see https://computerenhance.com for further information
|
||||||
|
;
|
||||||
|
; ========================================================================
|
||||||
|
|
||||||
|
; ========================================================================
|
||||||
|
; LISTING 42
|
||||||
|
; ========================================================================
|
||||||
|
|
||||||
|
;
|
||||||
|
; NOTE(casey): This is not meant to be a real compliance test for 8086
|
||||||
|
; disassemblers. It's just a reasonable selection of opcodes and patterns
|
||||||
|
; to use as a first pass in making sure a disassembler handles a large
|
||||||
|
; cross-section of the encoding. To be absolutely certain you haven't
|
||||||
|
; missed something, you would need a more exhaustive listing!
|
||||||
|
;
|
||||||
|
|
||||||
|
bits 16
|
||||||
|
|
||||||
|
mov si, bx
|
||||||
|
mov dh, al
|
||||||
|
mov cl, 12
|
||||||
|
mov ch, -12
|
||||||
|
mov cx, 12
|
||||||
|
mov cx, -12
|
||||||
|
mov dx, 3948
|
||||||
|
mov dx, -3948
|
||||||
|
mov al, [bx + si]
|
||||||
|
mov bx, [bp + di]
|
||||||
|
mov dx, [bp]
|
||||||
|
mov ah, [bx + si + 4]
|
||||||
|
mov al, [bx + si + 4999]
|
||||||
|
mov [bx + di], cx
|
||||||
|
mov [bp + si], cl
|
||||||
|
mov [bp], ch
|
||||||
|
mov ax, [bx + di - 37]
|
||||||
|
mov [si - 300], cx
|
||||||
|
mov dx, [bx - 32]
|
||||||
|
mov [bp + di], byte 7
|
||||||
|
mov [di + 901], word 347
|
||||||
|
mov bp, [5]
|
||||||
|
mov bx, [3458]
|
||||||
|
mov ax, [2555]
|
||||||
|
mov ax, [16]
|
||||||
|
mov [2554], ax
|
||||||
|
mov [15], ax
|
||||||
|
|
||||||
|
push word [bp + si]
|
||||||
|
push word [3000]
|
||||||
|
push word [bx + di - 30]
|
||||||
|
push cx
|
||||||
|
push ax
|
||||||
|
push dx
|
||||||
|
push cs
|
||||||
|
|
||||||
|
pop word [bp + si]
|
||||||
|
pop word [3]
|
||||||
|
pop word [bx + di - 3000]
|
||||||
|
pop sp
|
||||||
|
pop di
|
||||||
|
pop si
|
||||||
|
pop ds
|
||||||
|
|
||||||
|
xchg ax, [bp - 1000]
|
||||||
|
xchg [bx + 50], bp
|
||||||
|
|
||||||
|
xchg ax, ax
|
||||||
|
xchg ax, dx
|
||||||
|
xchg ax, sp
|
||||||
|
xchg ax, si
|
||||||
|
xchg ax, di
|
||||||
|
|
||||||
|
xchg cx, dx
|
||||||
|
xchg si, cx
|
||||||
|
xchg cl, ah
|
||||||
|
|
||||||
|
in al, 200
|
||||||
|
in al, dx
|
||||||
|
in ax, dx
|
||||||
|
|
||||||
|
out 44, ax
|
||||||
|
out dx, al
|
||||||
|
|
||||||
|
xlat
|
||||||
|
lea ax, [bx + di + 1420]
|
||||||
|
lea bx, [bp - 50]
|
||||||
|
lea sp, [bp - 1003]
|
||||||
|
lea di, [bx + si - 7]
|
||||||
|
|
||||||
|
lds ax, [bx + di + 1420]
|
||||||
|
lds bx, [bp - 50]
|
||||||
|
lds sp, [bp - 1003]
|
||||||
|
lds di, [bx + si - 7]
|
||||||
|
|
||||||
|
les ax, [bx + di + 1420]
|
||||||
|
les bx, [bp - 50]
|
||||||
|
les sp, [bp - 1003]
|
||||||
|
les di, [bx + si - 7]
|
||||||
|
|
||||||
|
lahf
|
||||||
|
sahf
|
||||||
|
pushf
|
||||||
|
popf
|
||||||
|
|
||||||
|
add cx, [bp]
|
||||||
|
add dx, [bx + si]
|
||||||
|
add [bp + di + 5000], ah
|
||||||
|
add [bx], al
|
||||||
|
add sp, 392
|
||||||
|
add si, 5
|
||||||
|
add ax, 1000
|
||||||
|
add ah, 30
|
||||||
|
add al, 9
|
||||||
|
add cx, bx
|
||||||
|
add ch, al
|
||||||
|
|
||||||
|
adc cx, [bp]
|
||||||
|
adc dx, [bx + si]
|
||||||
|
adc [bp + di + 5000], ah
|
||||||
|
adc [bx], al
|
||||||
|
adc sp, 392
|
||||||
|
adc si, 5
|
||||||
|
adc ax, 1000
|
||||||
|
adc ah, 30
|
||||||
|
adc al, 9
|
||||||
|
adc cx, bx
|
||||||
|
adc ch, al
|
||||||
|
|
||||||
|
inc ax
|
||||||
|
inc cx
|
||||||
|
inc dh
|
||||||
|
inc al
|
||||||
|
inc ah
|
||||||
|
inc sp
|
||||||
|
inc di
|
||||||
|
inc byte [bp + 1002]
|
||||||
|
inc word [bx + 39]
|
||||||
|
inc byte [bx + si + 5]
|
||||||
|
inc word [bp + di - 10044]
|
||||||
|
inc word [9349]
|
||||||
|
inc byte [bp]
|
||||||
|
|
||||||
|
aaa
|
||||||
|
daa
|
||||||
|
|
||||||
|
sub cx, [bp]
|
||||||
|
sub dx, [bx + si]
|
||||||
|
sub [bp + di + 5000], ah
|
||||||
|
sub [bx], al
|
||||||
|
sub sp, 392
|
||||||
|
sub si, 5
|
||||||
|
sub ax, 1000
|
||||||
|
sub ah, 30
|
||||||
|
sub al, 9
|
||||||
|
sub cx, bx
|
||||||
|
sub ch, al
|
||||||
|
|
||||||
|
sbb cx, [bp]
|
||||||
|
sbb dx, [bx + si]
|
||||||
|
sbb [bp + di + 5000], ah
|
||||||
|
sbb [bx], al
|
||||||
|
sbb sp, 392
|
||||||
|
sbb si, 5
|
||||||
|
sbb ax, 1000
|
||||||
|
sbb ah, 30
|
||||||
|
sbb al, 9
|
||||||
|
sbb cx, bx
|
||||||
|
sbb ch, al
|
||||||
|
|
||||||
|
dec ax
|
||||||
|
dec cx
|
||||||
|
dec dh
|
||||||
|
dec al
|
||||||
|
dec ah
|
||||||
|
dec sp
|
||||||
|
dec di
|
||||||
|
dec byte [bp + 1002]
|
||||||
|
dec word [bx + 39]
|
||||||
|
dec byte [bx + si + 5]
|
||||||
|
dec word [bp + di - 10044]
|
||||||
|
dec word [9349]
|
||||||
|
dec byte [bp]
|
||||||
|
|
||||||
|
neg ax
|
||||||
|
neg cx
|
||||||
|
neg dh
|
||||||
|
neg al
|
||||||
|
neg ah
|
||||||
|
neg sp
|
||||||
|
neg di
|
||||||
|
neg byte [bp + 1002]
|
||||||
|
neg word [bx + 39]
|
||||||
|
neg byte [bx + si + 5]
|
||||||
|
neg word [bp + di - 10044]
|
||||||
|
neg word [9349]
|
||||||
|
neg byte [bp]
|
||||||
|
|
||||||
|
cmp bx, cx
|
||||||
|
cmp dh, [bp + 390]
|
||||||
|
cmp [bp + 2], si
|
||||||
|
cmp bl, 20
|
||||||
|
cmp byte [bx], 34
|
||||||
|
cmp ax, 23909
|
||||||
|
|
||||||
|
aas
|
||||||
|
das
|
||||||
|
|
||||||
|
mul al
|
||||||
|
mul cx
|
||||||
|
mul word [bp]
|
||||||
|
mul byte [bx + di + 500]
|
||||||
|
|
||||||
|
imul ch
|
||||||
|
imul dx
|
||||||
|
imul byte [bx]
|
||||||
|
imul word [9483]
|
||||||
|
|
||||||
|
aam
|
||||||
|
|
||||||
|
div bl
|
||||||
|
div sp
|
||||||
|
div byte [bx + si + 2990]
|
||||||
|
div word [bp + di + 1000]
|
||||||
|
|
||||||
|
idiv ax
|
||||||
|
idiv si
|
||||||
|
idiv byte [bp + si]
|
||||||
|
idiv word [bx + 493]
|
||||||
|
|
||||||
|
aad
|
||||||
|
cbw
|
||||||
|
cwd
|
||||||
|
|
||||||
|
not ah
|
||||||
|
not bl
|
||||||
|
not sp
|
||||||
|
not si
|
||||||
|
not word [bp]
|
||||||
|
not byte [bp + 9905]
|
||||||
|
|
||||||
|
shl ah, 1
|
||||||
|
shr ax, 1
|
||||||
|
sar bx, 1
|
||||||
|
rol cx, 1
|
||||||
|
ror dh, 1
|
||||||
|
rcl sp, 1
|
||||||
|
rcr bp, 1
|
||||||
|
|
||||||
|
shl word [bp + 5], 1
|
||||||
|
shr byte [bx + si - 199], 1
|
||||||
|
sar byte [bx + di - 300], 1
|
||||||
|
rol word [bp], 1
|
||||||
|
ror word [4938], 1
|
||||||
|
rcl byte [3], 1
|
||||||
|
rcr word [bx], 1
|
||||||
|
|
||||||
|
shl ah, cl
|
||||||
|
shr ax, cl
|
||||||
|
sar bx, cl
|
||||||
|
rol cx, cl
|
||||||
|
ror dh, cl
|
||||||
|
rcl sp, cl
|
||||||
|
rcr bp, cl
|
||||||
|
|
||||||
|
shl word [bp + 5], cl
|
||||||
|
shr word [bx + si - 199], cl
|
||||||
|
sar byte [bx + di - 300], cl
|
||||||
|
rol byte [bp], cl
|
||||||
|
ror byte [4938], cl
|
||||||
|
rcl byte [3], cl
|
||||||
|
rcr word [bx], cl
|
||||||
|
|
||||||
|
and al, ah
|
||||||
|
and ch, cl
|
||||||
|
and bp, si
|
||||||
|
and di, sp
|
||||||
|
and al, 93
|
||||||
|
and ax, 20392
|
||||||
|
and [bp + si + 10], ch
|
||||||
|
and [bx + di + 1000], dx
|
||||||
|
and bx, [bp]
|
||||||
|
and cx, [4384]
|
||||||
|
and byte [bp - 39], 239
|
||||||
|
and word [bx + si - 4332], 10328
|
||||||
|
|
||||||
|
test bx, cx
|
||||||
|
test dh, [bp + 390]
|
||||||
|
test [bp + 2], si
|
||||||
|
test bl, 20
|
||||||
|
test byte [bx], 34
|
||||||
|
test ax, 23909
|
||||||
|
|
||||||
|
or al, ah
|
||||||
|
or ch, cl
|
||||||
|
or bp, si
|
||||||
|
or di, sp
|
||||||
|
or al, 93
|
||||||
|
or ax, 20392
|
||||||
|
or [bp + si + 10], ch
|
||||||
|
or [bx + di + 1000], dx
|
||||||
|
or bx, [bp]
|
||||||
|
or cx, [4384]
|
||||||
|
or byte [bp - 39], 239
|
||||||
|
or word [bx + si - 4332], 10328
|
||||||
|
|
||||||
|
xor al, ah
|
||||||
|
xor ch, cl
|
||||||
|
xor bp, si
|
||||||
|
xor di, sp
|
||||||
|
xor al, 93
|
||||||
|
xor ax, 20392
|
||||||
|
xor [bp + si + 10], ch
|
||||||
|
xor [bx + di + 1000], dx
|
||||||
|
xor bx, [bp]
|
||||||
|
xor cx, [4384]
|
||||||
|
xor byte [bp - 39], 239
|
||||||
|
xor word [bx + si - 4332], 10328
|
||||||
|
|
||||||
|
rep movsb
|
||||||
|
rep cmpsb
|
||||||
|
rep scasb
|
||||||
|
rep lodsb
|
||||||
|
rep movsw
|
||||||
|
rep cmpsw
|
||||||
|
rep scasw
|
||||||
|
rep lodsw
|
||||||
|
|
||||||
|
; NOTE(casey): Special thanks (as always!) to Mārtiņš Možeiko for figuring out why NASM
|
||||||
|
; wouldn't compile "rep stds" instructions. It was because it was a misprint in the 8086
|
||||||
|
; manual! It was really just "rep stos", which of course is still in x64, and NASM
|
||||||
|
; assembles it just fine.
|
||||||
|
rep stosb
|
||||||
|
rep stosw
|
||||||
|
|
||||||
|
call [39201]
|
||||||
|
call [bp - 100]
|
||||||
|
call sp
|
||||||
|
call ax
|
||||||
|
|
||||||
|
jmp ax
|
||||||
|
jmp di
|
||||||
|
jmp [12]
|
||||||
|
jmp [4395]
|
||||||
|
|
||||||
|
ret -7
|
||||||
|
ret 500
|
||||||
|
ret
|
||||||
|
|
||||||
|
label:
|
||||||
|
je label
|
||||||
|
jl label
|
||||||
|
jle label
|
||||||
|
jb label
|
||||||
|
jbe label
|
||||||
|
jp label
|
||||||
|
jo label
|
||||||
|
js label
|
||||||
|
jne label
|
||||||
|
jnl label
|
||||||
|
jg label
|
||||||
|
jnb label
|
||||||
|
ja label
|
||||||
|
jnp label
|
||||||
|
jno label
|
||||||
|
jns label
|
||||||
|
loop label
|
||||||
|
loopz label
|
||||||
|
loopnz label
|
||||||
|
jcxz label
|
||||||
|
|
||||||
|
int 13
|
||||||
|
int3
|
||||||
|
|
||||||
|
into
|
||||||
|
iret
|
||||||
|
|
||||||
|
clc
|
||||||
|
cmc
|
||||||
|
stc
|
||||||
|
cld
|
||||||
|
std
|
||||||
|
cli
|
||||||
|
sti
|
||||||
|
hlt
|
||||||
|
wait
|
||||||
|
|
||||||
|
lock not byte [bp + 9905]
|
||||||
|
lock xchg [100], al
|
||||||
|
|
||||||
|
mov al, cs:[bx + si]
|
||||||
|
mov bx, ds:[bp + di]
|
||||||
|
mov dx, es:[bp]
|
||||||
|
mov ah, ss:[bx + si + 4]
|
||||||
|
|
||||||
|
and ss:[bp + si + 10], ch
|
||||||
|
or ds:[bx + di + 1000], dx
|
||||||
|
xor bx, es:[bp]
|
||||||
|
cmp cx, es:[4384]
|
||||||
|
test byte cs:[bp - 39], 239
|
||||||
|
sbb word cs:[bx + si - 4332], 10328
|
||||||
|
|
||||||
|
lock not byte CS:[bp + 9905]
|
||||||
|
|
||||||
|
;
|
||||||
|
; NOTE(casey): These were not in the original homework set, but have been added since, as people
|
||||||
|
; found instruction encodings that were not previously covered. Thank you to everyone who
|
||||||
|
; submitted test cases!
|
||||||
|
;
|
||||||
|
|
||||||
|
call 123:456
|
||||||
|
jmp 789:34
|
||||||
|
|
||||||
|
mov [bx+si+59],es
|
||||||
|
|
||||||
|
jmp 2620
|
||||||
|
call 11804
|
||||||
|
|
||||||
|
retf 17556
|
||||||
|
ret 17560
|
||||||
|
retf
|
||||||
|
ret
|
||||||
|
|
||||||
|
call [bp+si-0x3a]
|
||||||
|
call far [bp+si-0x3a]
|
||||||
|
jmp [di]
|
||||||
|
jmp far [di]
|
||||||
|
|
||||||
|
jmp 21862:30600
|
||||||
|
|
||||||
|
;
|
||||||
|
; TODO(casey): I would like to uncomment this, but as far as I can tell, NASM doesn't recognize the ESC instruction :(
|
||||||
|
; so even if I just force the assembler to output the bits here, our disasm will fail to assemble because it will (correctly!)
|
||||||
|
; print the esc instruction and NASM will error because it doesn't know what that is.
|
||||||
|
;
|
||||||
|
; esc 938,ax
|
||||||
|
;
|
||||||
|
|
||||||
|
;
|
||||||
|
; TODO(casey): According to NASM, "rep movsb" is "not lockable". However the 8086 manual seems to think it is, and
|
||||||
|
; even describes what happens when you you lock a rep: the lock is held for the duration of the rep operation. So...
|
||||||
|
; yeah. Not sure why this doesn't work in NASM:
|
||||||
|
;
|
||||||
|
; lock rep movsb
|
||||||
|
;
|
173
decoder8086.odin
173
decoder8086.odin
@ -20,6 +20,9 @@ Register :: struct {
|
|||||||
OpName :: enum {
|
OpName :: enum {
|
||||||
TBD,
|
TBD,
|
||||||
MOV,
|
MOV,
|
||||||
|
PUSH,
|
||||||
|
POP,
|
||||||
|
XCHG,
|
||||||
ADD,
|
ADD,
|
||||||
SUB,
|
SUB,
|
||||||
CMP,
|
CMP,
|
||||||
@ -69,6 +72,13 @@ registers := [8]Register {
|
|||||||
{fullname = "di", bytename = "bh", code = 0b111},
|
{fullname = "di", bytename = "bh", code = 0b111},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
segment_registers := [4]Register {
|
||||||
|
{fullname = "es", code = 0b000},
|
||||||
|
{fullname = "cs", code = 0b001},
|
||||||
|
{fullname = "ss", code = 0b010},
|
||||||
|
{fullname = "ds", code = 0b011},
|
||||||
|
}
|
||||||
|
|
||||||
RegInfo :: struct {
|
RegInfo :: struct {
|
||||||
in_first_byte: bool,
|
in_first_byte: bool,
|
||||||
shift_offset: u8,
|
shift_offset: u8,
|
||||||
@ -82,11 +92,61 @@ OpCodeId :: enum {
|
|||||||
|
|
||||||
LastBit :: struct{}
|
LastBit :: struct{}
|
||||||
FourthBit :: struct{}
|
FourthBit :: struct{}
|
||||||
|
Force :: struct{}
|
||||||
|
|
||||||
WordSize :: union {
|
WordSize :: union {
|
||||||
None,
|
None,
|
||||||
LastBit,
|
LastBit,
|
||||||
FourthBit,
|
FourthBit,
|
||||||
|
Force,
|
||||||
|
}
|
||||||
|
|
||||||
|
None :: struct {}
|
||||||
|
|
||||||
|
Disp8 :: i8
|
||||||
|
Disp16 :: i16
|
||||||
|
Displacement :: union {
|
||||||
|
None,
|
||||||
|
Disp8,
|
||||||
|
Disp16
|
||||||
|
}
|
||||||
|
|
||||||
|
Value8 :: i8
|
||||||
|
Value16 :: i16
|
||||||
|
Data :: union {
|
||||||
|
None,
|
||||||
|
Value8,
|
||||||
|
Value16
|
||||||
|
}
|
||||||
|
|
||||||
|
ModMemory :: struct {}
|
||||||
|
Mod8BitDisp :: i8
|
||||||
|
Mod16BitDisp :: i16
|
||||||
|
ModRegister :: struct {}
|
||||||
|
|
||||||
|
ModMode :: union {
|
||||||
|
ModMemory,
|
||||||
|
Mod8BitDisp,
|
||||||
|
Mod16BitDisp,
|
||||||
|
ModRegister,
|
||||||
|
}
|
||||||
|
|
||||||
|
RegisterId :: distinct u8
|
||||||
|
Immediate8 :: distinct i8
|
||||||
|
Immediate16 :: distinct i16
|
||||||
|
MemoryAddr :: struct {
|
||||||
|
addr_id: u8,
|
||||||
|
displacement: Displacement
|
||||||
|
}
|
||||||
|
Accumulator :: distinct i16
|
||||||
|
SegmentRegister :: distinct i8
|
||||||
|
OperandType :: union {
|
||||||
|
RegisterId,
|
||||||
|
Immediate8,
|
||||||
|
Immediate16,
|
||||||
|
MemoryAddr,
|
||||||
|
Accumulator,
|
||||||
|
SegmentRegister,
|
||||||
}
|
}
|
||||||
|
|
||||||
InstructionInfo :: struct {
|
InstructionInfo :: struct {
|
||||||
@ -99,17 +159,19 @@ InstructionInfo :: struct {
|
|||||||
reg_info: Maybe(RegInfo),
|
reg_info: Maybe(RegInfo),
|
||||||
has_data: bool,
|
has_data: bool,
|
||||||
has_address: bool,
|
has_address: bool,
|
||||||
has_accumulator: bool,
|
uses_accumulator: bool,
|
||||||
has_segreg: bool,
|
has_segreg: bool,
|
||||||
has_flip: bool,
|
has_flip: bool,
|
||||||
has_sign_extension: bool,
|
has_sign_extension: bool,
|
||||||
is_jump: bool,
|
is_jump: bool,
|
||||||
|
is_unary: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Maybe we can get rid of it since I don't have to specify the shift_offset,
|
// TODO: Maybe we can get rid of it since I don't have to specify the shift_offset,
|
||||||
// not like it changes a lot
|
// not like it changes a lot
|
||||||
reg_first_last := RegInfo{ in_first_byte = true, shift_offset = 0 }
|
reg_first_last := RegInfo{ in_first_byte = true, shift_offset = 0 }
|
||||||
reg_second_middle := RegInfo{ in_first_byte = false, shift_offset = 3 }
|
reg_second_middle := RegInfo{ in_first_byte = false, shift_offset = 3 }
|
||||||
|
reg_first_middle := RegInfo{ in_first_byte = true, shift_offset = 3 }
|
||||||
|
|
||||||
instructions := [?]InstructionInfo {
|
instructions := [?]InstructionInfo {
|
||||||
{ opname = .MOV, desc = "Register/memory to/from register", mask = 0b11111100, encoding = 0b10001000,
|
{ opname = .MOV, desc = "Register/memory to/from register", mask = 0b11111100, encoding = 0b10001000,
|
||||||
@ -119,13 +181,29 @@ instructions := [?]InstructionInfo {
|
|||||||
{ opname = .MOV, desc = "Immediate to register", mask = 0b11110000, encoding = 0b10110000,
|
{ opname = .MOV, desc = "Immediate to register", mask = 0b11110000, encoding = 0b10110000,
|
||||||
reg_info = reg_first_last, has_data = true, word_size = FourthBit{} },
|
reg_info = reg_first_last, has_data = true, word_size = FourthBit{} },
|
||||||
{ opname = .MOV, desc = "Memory to accumulator", mask = 0b11111110, encoding = 0b10100000,
|
{ opname = .MOV, desc = "Memory to accumulator", mask = 0b11111110, encoding = 0b10100000,
|
||||||
has_flip = true, word_size = LastBit{}, has_accumulator = true },
|
has_flip = true, word_size = LastBit{}, uses_accumulator = true },
|
||||||
{ opname = .MOV, desc = "Accumulator to memory", mask = 0b11111110, encoding = 0b10100010,
|
{ opname = .MOV, desc = "Accumulator to memory", mask = 0b11111110, encoding = 0b10100010,
|
||||||
has_flip = true, word_size = LastBit{}, has_accumulator = true },
|
has_flip = true, word_size = LastBit{}, uses_accumulator = true },
|
||||||
{ opname = .MOV, desc = "Register/memory to segment register", mask = 0b11111111, encoding = 0b10001110,
|
{ opname = .MOV, desc = "Register/memory to segment register", mask = 0b11111111, encoding = 0b10001110,
|
||||||
has_segreg = true, has_address = true, word_size = None{} },
|
has_segreg = true, has_address = true, word_size = None{} },
|
||||||
{ opname = .MOV, desc = "Segment register to register/memory", mask = 0b11111111, encoding = 0b10001100,
|
{ opname = .MOV, desc = "Segment register to register/memory", mask = 0b11111111, encoding = 0b10001100,
|
||||||
has_segreg = true, has_address = true, word_size = None{} },
|
has_segreg = true, has_address = true, word_size = None{} },
|
||||||
|
{ opname = .PUSH, desc = "", mask = 0b11111111, encoding = 0b11111111,
|
||||||
|
has_address = true, word_size = None{}, is_unary = true },
|
||||||
|
{ opname = .PUSH, desc = "", mask = 0b11111000, encoding = 0b01010000,
|
||||||
|
reg_info = reg_first_last, word_size = Force{}, is_unary = true },
|
||||||
|
{ opname = .PUSH, desc = "", mask = 0b11100111, encoding = 0b00000110,
|
||||||
|
has_segreg = true, reg_info = reg_first_middle, word_size = Force{}, is_unary = true },
|
||||||
|
{ opname = .POP, desc = "", mask = 0b11111111, encoding = 0b10001111,
|
||||||
|
has_address = true, word_size = None{}, is_unary = true },
|
||||||
|
{ opname = .POP, desc = "", mask = 0b11111000, encoding = 0b01011000,
|
||||||
|
reg_info = reg_first_last, word_size = Force{}, is_unary = true },
|
||||||
|
{ opname = .POP, desc = "", mask = 0b11100111, encoding = 0b00000111,
|
||||||
|
has_segreg = true, reg_info = reg_first_middle, word_size = None{}, is_unary = true },
|
||||||
|
{ opname = .XCHG, desc = "", mask = 0b11111110, encoding = 0b10000110,
|
||||||
|
reg_info = reg_second_middle, has_address = true, word_size = LastBit{}, has_flip = true},
|
||||||
|
{ opname = .XCHG, desc = "", mask = 0b11111000, encoding = 0b10010000,
|
||||||
|
reg_info = reg_first_last, uses_accumulator = true, word_size = Force{}, },
|
||||||
{ opname = .TBD, desc = "Reg/memory with register to either", mask = 0b11000100, encoding = 0b00000000,
|
{ opname = .TBD, desc = "Reg/memory with register to either", mask = 0b11000100, encoding = 0b00000000,
|
||||||
opcode_id = .First, reg_info = reg_second_middle, has_address = true, word_size = LastBit{}, has_flip = true },
|
opcode_id = .First, reg_info = reg_second_middle, has_address = true, word_size = LastBit{}, has_flip = true },
|
||||||
{ opname = .TBD, desc = "Immediate to register/memory", mask = 0b11111100, encoding = 0b10000000,
|
{ opname = .TBD, desc = "Immediate to register/memory", mask = 0b11111100, encoding = 0b10000000,
|
||||||
@ -182,52 +260,6 @@ instructions := [?]InstructionInfo {
|
|||||||
{ opname = .JCXZ, desc = "Jump on not zero", mask = 0b11111111, encoding = 0b11100011, is_jump = true},
|
{ opname = .JCXZ, desc = "Jump on not zero", mask = 0b11111111, encoding = 0b11100011, is_jump = true},
|
||||||
}
|
}
|
||||||
|
|
||||||
None :: struct {}
|
|
||||||
|
|
||||||
Disp8 :: i8
|
|
||||||
Disp16 :: i16
|
|
||||||
Displacement :: union {
|
|
||||||
None,
|
|
||||||
Disp8,
|
|
||||||
Disp16
|
|
||||||
}
|
|
||||||
|
|
||||||
Value8 :: i8
|
|
||||||
Value16 :: i16
|
|
||||||
Data :: union {
|
|
||||||
None,
|
|
||||||
Value8,
|
|
||||||
Value16
|
|
||||||
}
|
|
||||||
|
|
||||||
ModMemory :: struct {}
|
|
||||||
Mod8BitDisp :: i8
|
|
||||||
Mod16BitDisp :: i16
|
|
||||||
ModRegister :: struct {}
|
|
||||||
|
|
||||||
ModMode :: union {
|
|
||||||
ModMemory,
|
|
||||||
Mod8BitDisp,
|
|
||||||
Mod16BitDisp,
|
|
||||||
ModRegister,
|
|
||||||
}
|
|
||||||
|
|
||||||
RegisterId :: distinct u8
|
|
||||||
Immediate8 :: distinct i8
|
|
||||||
Immediate16 :: distinct i16
|
|
||||||
MemoryAddr :: struct {
|
|
||||||
addr_id: u8,
|
|
||||||
displacement: Displacement
|
|
||||||
}
|
|
||||||
Accumulator :: distinct i16
|
|
||||||
OperandType :: union {
|
|
||||||
RegisterId,
|
|
||||||
Immediate8,
|
|
||||||
Immediate16,
|
|
||||||
MemoryAddr,
|
|
||||||
Accumulator,
|
|
||||||
}
|
|
||||||
|
|
||||||
inst_map := make(map[u8]InstructionInfo)
|
inst_map := make(map[u8]InstructionInfo)
|
||||||
RIGHT_ALIGN_AMOUNT := 35
|
RIGHT_ALIGN_AMOUNT := 35
|
||||||
|
|
||||||
@ -285,6 +317,8 @@ get_memory_type_string :: proc(mem_type: OperandType, is_word: bool) -> string {
|
|||||||
string_val = get_memory_string(val)
|
string_val = get_memory_string(val)
|
||||||
case Accumulator:
|
case Accumulator:
|
||||||
string_val = fmt.aprintf("[%d]", val)
|
string_val = fmt.aprintf("[%d]", val)
|
||||||
|
case SegmentRegister:
|
||||||
|
string_val = segment_registers[val].fullname
|
||||||
}
|
}
|
||||||
return string_val
|
return string_val
|
||||||
}
|
}
|
||||||
@ -352,7 +386,7 @@ main :: proc() {
|
|||||||
}
|
}
|
||||||
defer os.close(f)
|
defer os.close(f)
|
||||||
|
|
||||||
data := make([]u8, 512)
|
data := make([]u8, 1024)
|
||||||
bytes_read, err2 := os.read(f, data)
|
bytes_read, err2 := os.read(f, data)
|
||||||
if err2 != nil {
|
if err2 != nil {
|
||||||
// ...
|
// ...
|
||||||
@ -369,13 +403,17 @@ main :: proc() {
|
|||||||
// asdf :u16 = 0b00000011_11101000
|
// asdf :u16 = 0b00000011_11101000
|
||||||
// asdf2 :i16 = (i16)(asdf)
|
// asdf2 :i16 = (i16)(asdf)
|
||||||
// fmt.printfln("%d", asdf2)
|
// fmt.printfln("%d", asdf2)
|
||||||
|
print_at_end := false
|
||||||
read_next := false
|
read_next := false
|
||||||
src_dst := true
|
src_dst := true
|
||||||
idx := 0
|
idx := 0
|
||||||
added_label := false
|
added_label := false
|
||||||
line_count := 0
|
line_count := 0
|
||||||
|
// last_opname: string
|
||||||
|
last_opname: [3]byte
|
||||||
instruction_builder := strings.builder_make()
|
instruction_builder := strings.builder_make()
|
||||||
instruction_list := make([dynamic]string, 128)
|
instruction_list := make([dynamic]string, 512)
|
||||||
|
fmt.println("bits 16")
|
||||||
for idx < bytes_read {
|
for idx < bytes_read {
|
||||||
processed := 1
|
processed := 1
|
||||||
curr_byte := data[idx]
|
curr_byte := data[idx]
|
||||||
@ -408,6 +446,7 @@ main :: proc() {
|
|||||||
switch val in instruction.word_size {
|
switch val in instruction.word_size {
|
||||||
case LastBit: is_word = curr_byte & 1 == 1
|
case LastBit: is_word = curr_byte & 1 == 1
|
||||||
case FourthBit: is_word = curr_byte & 0b0000_1000 != 0
|
case FourthBit: is_word = curr_byte & 0b0000_1000 != 0
|
||||||
|
case Force: is_word = true
|
||||||
case None:
|
case None:
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -445,6 +484,10 @@ main :: proc() {
|
|||||||
} else if mod == 3 {
|
} else if mod == 3 {
|
||||||
lhs2 = (RegisterId)(registers[rm].code)
|
lhs2 = (RegisterId)(registers[rm].code)
|
||||||
}
|
}
|
||||||
|
} else if instruction.has_segreg {
|
||||||
|
lhs2 = (SegmentRegister)(segment_registers[reg].code)
|
||||||
|
} else if instruction.uses_accumulator {
|
||||||
|
lhs2 = (RegisterId)(registers[0].code)
|
||||||
} else {
|
} else {
|
||||||
lhs2 = (RegisterId)(registers[reg].code)
|
lhs2 = (RegisterId)(registers[reg].code)
|
||||||
}
|
}
|
||||||
@ -456,12 +499,16 @@ main :: proc() {
|
|||||||
processed += word_signed ? 2 : 1
|
processed += word_signed ? 2 : 1
|
||||||
rhs2 = (OperandType)(word_signed ? (Immediate16)(get_i16(data[data_idx:])) : (Immediate8)(data[data_idx]))
|
rhs2 = (OperandType)(word_signed ? (Immediate16)(get_i16(data[data_idx:])) : (Immediate8)(data[data_idx]))
|
||||||
has_immediate = true
|
has_immediate = true
|
||||||
} else if instruction.has_accumulator {
|
} else if instruction.uses_accumulator {
|
||||||
|
if _, ok := instruction.word_size.(LastBit); ok {
|
||||||
processed += is_word ? 2 : 1
|
processed += is_word ? 2 : 1
|
||||||
rhs2 = (OperandType)(is_word ? (Accumulator)(get_i16(data[data_idx:])) : (Accumulator)(data[data_idx]))
|
rhs2 = (OperandType)(is_word ? (Accumulator)(get_i16(data[data_idx:])) : (Accumulator)(data[data_idx]))
|
||||||
} else {
|
} else {
|
||||||
rhs2 = (RegisterId)(reg)
|
rhs2 = (RegisterId)(reg)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
rhs2 = (RegisterId)(reg)
|
||||||
|
}
|
||||||
|
|
||||||
if flip_dst {
|
if flip_dst {
|
||||||
lhs2, rhs2 = rhs2, lhs2
|
lhs2, rhs2 = rhs2, lhs2
|
||||||
@ -486,6 +533,11 @@ main :: proc() {
|
|||||||
value := (i8)(data[idx+1]) + 2
|
value := (i8)(data[idx+1]) + 2
|
||||||
full_inst = fmt.aprintf("%s $%s%d ; %d", strings.to_lower(opname), value >= 0 ? "+" : "", value, value - 2)
|
full_inst = fmt.aprintf("%s $%s%d ; %d", strings.to_lower(opname), value >= 0 ? "+" : "", value, value - 2)
|
||||||
processed += 1
|
processed += 1
|
||||||
|
} else if instruction.is_unary {
|
||||||
|
if instruction.has_address {
|
||||||
|
size_string = "word "
|
||||||
|
}
|
||||||
|
full_inst = fmt.aprintf("%s %s%s", opname, size_string, lhs)
|
||||||
} else {
|
} else {
|
||||||
opname = strings.to_lower(opname)
|
opname = strings.to_lower(opname)
|
||||||
if opname == "mov" {
|
if opname == "mov" {
|
||||||
@ -498,13 +550,28 @@ main :: proc() {
|
|||||||
for i in 0..<processed {
|
for i in 0..<processed {
|
||||||
fmt.sbprintf(&instruction_builder, " %08b", data[idx + i])
|
fmt.sbprintf(&instruction_builder, " %08b", data[idx + i])
|
||||||
}
|
}
|
||||||
|
if print_at_end {
|
||||||
instruction_list[line_count] = strings.clone(strings.to_string(instruction_builder))
|
instruction_list[line_count] = strings.clone(strings.to_string(instruction_builder))
|
||||||
|
} else {
|
||||||
|
op := strings.to_string(instruction_builder)
|
||||||
|
if op[0:3] != string(last_opname[:]) {
|
||||||
|
fmt.println()
|
||||||
|
}
|
||||||
|
copy(last_opname[:], op[0:3])
|
||||||
|
fmt.println(op)
|
||||||
|
}
|
||||||
idx += processed
|
idx += processed
|
||||||
line_count += 1
|
line_count += 1
|
||||||
strings.builder_reset(&instruction_builder)
|
strings.builder_reset(&instruction_builder)
|
||||||
}
|
}
|
||||||
fmt.println("bits 16\n")
|
if print_at_end {
|
||||||
for i in 0..<line_count {
|
for i in 0..<line_count {
|
||||||
|
opname := instruction_list[i]
|
||||||
|
if !strings.has_prefix(opname, string(last_opname[:])) {
|
||||||
|
fmt.println()
|
||||||
|
}
|
||||||
|
copy(last_opname[:], opname[0:3])
|
||||||
fmt.println(instruction_list[i])
|
fmt.println(instruction_list[i])
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user