From: admin@nospicedham.127.0.0.1   
      
   On Thu, 29 Jul 2021 22:11:00 -0700 (PDT)   
   "luser...@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.   
   >   
   > 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 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 '-'   
    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   
    int 0x10 ; bios prtc   
    loop PutDigit   
      
      
      
      
      
      
      
   --   
   Bah, and indeed Humbug.   
      
   --- SoupGate-Win32 v1.05   
    * Origin: you cannot sedate... all the things you hate (1:229/2)   
|