diff --git a/lib/fcbparse.asm b/lib/fcbparse.asm new file mode 100644 index 0000000..eee48d7 --- /dev/null +++ b/lib/fcbparse.asm @@ -0,0 +1,46 @@ +; Parse ASCIIZ string into FCB +; IN SI ptr to filename +; BX ptr to FCB +fcb_parse: + push di + push ax + mov di, bx + xor ax, ax + stosb +.cleanout: + push di + mov cx, 0x0A + mov al, 0x20 + rep stosb + pop di +.base_loop: + call .read + cmp al, 0x2E + je .ext_start + cmp al, 0x20 + je .ret + stosb + jmp .base_loop +.ext_start: + mov di, bx + add di, 9 +.ext_loop: + call .read + cmp al, 0x20 + je .ret + stosb + jmp .ext_loop +.read: + lodsb + test al, al + jz .eret + cmp al, 0x0D + je .eret + ret +.eret: + dec si + pop ax +.ret: + pop ax + pop di + ret diff --git a/programs/lst2bin.asm b/programs/lst2bin.asm new file mode 100644 index 0000000..f0d32b5 --- /dev/null +++ b/programs/lst2bin.asm @@ -0,0 +1,18 @@ +org 0x100 + +jmp start + +%include "fcbparse.asm" + +fcb_in: + times 20 db 0 + +fcb_out: + times 20 db 0 + +start: + mov si, 0x81 + mov bx, fcb_in + mov ax, 0x1234 + call fcb_parse + ret diff --git a/utils/emul.c b/utils/emul.c index 1f8bc09..9e26c43 100644 --- a/utils/emul.c +++ b/utils/emul.c @@ -13,6 +13,7 @@ union regset { int carry, zero; uint16_t ip = 0x100; +uint16_t flags = 0; uint16_t scratch; uint16_t reg; int off; @@ -54,7 +55,29 @@ void dump() { printf("%s=%04X ", regnames[i], regset.r16[i]); } printf("\n"); - printf("IP=%04X : %X\n", ip, mem[ip]); + printf("IP=%04X : %02X %02X\n", ip, mem[ip], mem[ip+1]); +} + +void arith8(int op, int8_t* dst, int src) { + // I'll just assume this sign-extends + int t = *dst; + int p = *dst; + switch (op) { + case ADD: t += src; break; + case OR: t |= src; break; + case ADC: t += (src + carry); break; + case SBB: t -= (src + carry); break; + case AND: t &= src; break; + case SUB: t -= src; break; + case XOR: t ^= src; break; + case CMP: t -= src; break; + case TEST: t &= src; break; + } + zero=!t; + // I dont think the following is correct + carry=((t ^ p) >> 8) & 1; + if (op==CMP || op==TEST) return; + *dst = t; } void arith16(int op, int16_t* dst, int src) { @@ -192,6 +215,28 @@ void step() { uint8_t opcode = mem[ip]; ip++; switch(opcode) { + case 0x00: // ARITH r/m8,reg8 + case 0x08: + case 0x10: + case 0x18: + case 0x20: + case 0x28: + case 0x30: + case 0x38: + modrm(BIT8); + arith8(opcode >> 3, &RM8, R8(reg)); + break; + case 0x01: // ARITH r/m16,reg16 + case 0x09: + case 0x11: + case 0x19: + case 0x21: + case 0x29: + case 0x31: + case 0x39: + modrm(BIT16); + arith16(opcode >> 3, &RM16, R16(reg)); + break; case 0x50 ... 0x57: // PUSH reg16 push(R16(opcode-0x50)); break; @@ -216,6 +261,10 @@ void step() { modrm(BIT8); RM8 = R8(reg); break; + case 0x89: // MOV r/m16,reg16 + modrm(BIT16); + RM16 = R16(reg); + break; case 0x8B: // MOV reg16,r/m16 modrm(BIT16); R16(reg) = RM16; @@ -303,5 +352,6 @@ int main(int argc, char** argv) { fread(mem + ip, 1, sizeof(mem) - ip, fd); while(1) { step(); + dump(); } }