luser...@nospicedham.gmail.com
2021-07-30 05:11:00 UTC
I wrote this machine code to trace the LIT word in my forth interpreter.
Is it possible to tighten up this code? It's trying to print a 16bit signed
integer (ignoring INT_MIN) left to right with no leading zeros.
This is assembly code, but I hope you'll forgive my ideosyncratic syntax.
The operands map left to right to the reg and reg/mem fields into the
mod-reg-reg/mem byte and the opcodes target the "to" form (direction
field = 1), eg. in "MOV(,R,BX,AX)", BX is the dest, AX is the source, the
R is needed to select register-to-register mode (the mod field). The empty
first argument is for tweaks to the opcode which could be F (clear the
direction field by subtracting 2) or BYTE (clear the word field by subtracting 1).
It tests each digit for zero where it jumps over the int 10h call except
the last digit.
It occurs to me that the DIV instruction has a mod field. So that means
the divisor could be register indirect, right? like through SI or BX, maybe?
Then it could probably be rolled up in a loop, right? Sorry if I'm jumping
the gun asking for help before exerting the requisite effort.
CODE(lit, lit, LODS, PUSH(AX)
#ifdef TRACE
, MOV(,R,BX,AX), OR(,R,BX,BX), JGE,7, MOVI(AX,0x0E00+'-'), INT(10), NEG(R,BX),
MOV(,R,AX,BX), XOR(,R,DX,DX), MOVI(CX,10000), DIV(R,CX),
OR(,R,AX,AX), JZ,6, MOVBI(AH,0x0E), ADDAL(48), INT(10),
MOV(,R,AX,DX), XOR(,R,DX,DX), MOVI(CX,1000), DIV(R,CX),
OR(,R,AX,AX), JZ,6, MOVBI(AH,0x0E), ADDAL(48), INT(10),
MOV(,R,AX,DX), MOVBI(CL,100), XOR(BYTE,R,CH,CH), BYTE+DIV(R,CL),
MOV(BYTE,R,DL,AH),
OR(BYTE,R,AL,AL), JZ,6, MOVBI(AH,0x0E), ADDAL(48), INT(10),
MOV(BYTE,R,AL,DL), XOR(BYTE,R,AH,AH), MOVBI(CL,10), BYTE+DIV(R,CL),
MOV(BYTE,R,DL,AH),
OR(BYTE,R,AL,AL), JZ,6, MOVBI(AH,0x0E), ADDAL(48), INT(10),
MOVBI(AH,0x0E), MOV(BYTE,R,AL,DL), ADDAL(48), INT(10),
MOVI(AX,0x0E00+' '), INT(10)
#endif
)/**/
Is it possible to tighten up this code? It's trying to print a 16bit signed
integer (ignoring INT_MIN) left to right with no leading zeros.
This is assembly code, but I hope you'll forgive my ideosyncratic syntax.
The operands map left to right to the reg and reg/mem fields into the
mod-reg-reg/mem byte and the opcodes target the "to" form (direction
field = 1), eg. in "MOV(,R,BX,AX)", BX is the dest, AX is the source, the
R is needed to select register-to-register mode (the mod field). The empty
first argument is for tweaks to the opcode which could be F (clear the
direction field by subtracting 2) or BYTE (clear the word field by subtracting 1).
It tests each digit for zero where it jumps over the int 10h call except
the last digit.
It occurs to me that the DIV instruction has a mod field. So that means
the divisor could be register indirect, right? like through SI or BX, maybe?
Then it could probably be rolled up in a loop, right? Sorry if I'm jumping
the gun asking for help before exerting the requisite effort.
CODE(lit, lit, LODS, PUSH(AX)
#ifdef TRACE
, MOV(,R,BX,AX), OR(,R,BX,BX), JGE,7, MOVI(AX,0x0E00+'-'), INT(10), NEG(R,BX),
MOV(,R,AX,BX), XOR(,R,DX,DX), MOVI(CX,10000), DIV(R,CX),
OR(,R,AX,AX), JZ,6, MOVBI(AH,0x0E), ADDAL(48), INT(10),
MOV(,R,AX,DX), XOR(,R,DX,DX), MOVI(CX,1000), DIV(R,CX),
OR(,R,AX,AX), JZ,6, MOVBI(AH,0x0E), ADDAL(48), INT(10),
MOV(,R,AX,DX), MOVBI(CL,100), XOR(BYTE,R,CH,CH), BYTE+DIV(R,CL),
MOV(BYTE,R,DL,AH),
OR(BYTE,R,AL,AL), JZ,6, MOVBI(AH,0x0E), ADDAL(48), INT(10),
MOV(BYTE,R,AL,DL), XOR(BYTE,R,AH,AH), MOVBI(CL,10), BYTE+DIV(R,CL),
MOV(BYTE,R,DL,AH),
OR(BYTE,R,AL,AL), JZ,6, MOVBI(AH,0x0E), ADDAL(48), INT(10),
MOVBI(AH,0x0E), MOV(BYTE,R,AL,DL), ADDAL(48), INT(10),
MOVI(AX,0x0E00+' '), INT(10)
#endif
)/**/