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
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
)/**/
It's trying to print a 16bit signed integer (ignoring INT_MIN)...
left to right with no leading zeros.
It tests each digit for zero where it jumps over the int 10h call
except the last digit.
Is it possible to tighten up this code?
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?
Sorry if I'm jumping the gun asking for help before exerting the
requisite effort.
On Thu, 29 Jul 2021 22:11:00 -0700 (PDT)
"luser...@nospicedham.gmail.com" <luser.droog@nospicedham.gmail.com> wrote:
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.
I think I got the jist of it;
here's some std asm code from earlier, rejigged for int 0x10 - it requires 5 free stack positions.
uses ax,bx,cx,dx - 36 bytes
PrtNum: ; ax to con using int10 fn 0E: no leading spaces or zeros but show '-'I didn't test! Make that line:
test ax,ax ; Is it positive?
jge NotNeg
push ax
mov ax,0x0E00+'-'
int 0x10 ; bios prtc
pop ax
neg ax ; show as positive: hibit set only for 0x8000!# NotNeg:
mov bx,10 ; decimal
xor cx,cx ; Digit count (5 max)
NextDigit:
inc cx ; prt at least 1 digit (i.e. '0')
xor dx,dx ; clear prev, cant cwd for #8000
div bx
push dx ; Remainder is the digit
test ax,ax ; Is it zero yet?
jnz NextDigit
PutDigit:
pop ax ; get digit (000x)
add ax,0x0E+'0' ; digit to display value, prtfn in ah
loop PutDigit
--
Bah, and indeed Humbug.
luser,
It's trying to print a 16bit signed integer (ignoring INT_MIN)...
left to right with no leading zeros.
It tests each digit for zero where it jumps over the int 10h call
except the last digit.
Those two do not match. And as your code seem to be written according to the second ...
Try printing the value 3002 (or something else with embedded zeroes) to see what I mean.
Is it possible to tighten up this code?
I'm not sure what "tighten up" is ment to be read as. Smaller ? Faster ? In the first case, how many bytes is it now ?
My own, erstwhile "trick" was, while doing the same as you (dividing by the largest divisor first), to load a register with the divisor and than call a small routine doing the division and printing.
But in the light of your "skip leading zeroes" you could do worse than to look at what John posted, as that method automatically discards leading zeroes - it simply stops as soon as the remainder becomes zero. I'm not so sure about if that "loop" at the end will work though, as the INT 0x10 could easily trash cx..
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?
Yes, would work. And that same list can than also be used to skip leading zeroes.
Sorry if I'm jumping the gun asking for help before exerting the
requisite effort.
I can imagine that you ask, but I do not quite understand why you did not test your own code first ...
Regards,
Rudy Wieser
sure about if that "loop" at the end will work though, as the INT 0x10Seems to be OK on this "DOS" VDM under XP - but yes, the int 10 was
could easily trash cx..
put in for the OP - originally the code put to a buffer at di, with a
single
print (ah=9, Int 21) at the end.
On Thu, 29 Jul 2021 22:11:00 -0700 (PDT)
"luser...@nospicedham.gmail.com" <luser.droog@nospicedham.gmail.com>
wrote:
Sorry Frank,Sorry Rod for the delay in posting = you keep changing your address so
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.
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.
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 293 |
Nodes: | 16 (2 / 14) |
Uptime: | 223:10:40 |
Calls: | 6,623 |
Calls today: | 5 |
Files: | 12,171 |
Messages: | 5,318,354 |