Welcome to denMike's tiny page!
Home
Guestbook
Contact
 
Husky
 
Corona virus
Electronics
Fantasy
mtech.dk
Programming
  Resources in .exe Files

  Pascal Runtime Error 200

  The Pentium F0 bug

  Number Printing Routing

  Using the IOE Interrupt

 
Software
Space
Tilbud
Various Links
 
USA 2001
ISU MSS03
USA 2006
South Africa 2008


Last updated: September 16th, 1999
(Uploaded May 26th, 1997)
A tiny number printing routine.

There was a time when even the most advanced computer had just a few kilobytes of memory, and every byte of code was required to do double and triple duty. With the advent of multi-megabyte RAM boards, the need to pinch every byte has lessened, and programmers have indeed forgotten some of the old ways. Let ten programmers write an ASM program that outputs numbers and you'll get ten different algorithms, none as compact as the one shown here. It's amazing how much power is packed into the 30 bytes of code.

The assembly language routine below prints decimal numbers. If you enter the routine at the label dploop with 16 (10h) in CX, it will print hex; with 8, it will print octal; with 2, binary. Call pdig with a small number in DL and it will be printed as a digit; call pch and you'll print a single character. The number printing removes leading zerores, execpt for the special case of 0. The only 'magic' here is the use of the stack to store the remainders of successive divisions so that they can be unstacked and printed in proper order. They are not counted. The routine just calls itself recursively whenever there is a nonzero quotient and unwinds the calls to print each digit in turn. Since the routine can't escape without printing a digit, the zero case is handled automatically.

_dpt     PROC NEAR        ; Entry-point for printing in decimal
         mov  cx,10
dploop:                   ; Entry-point for printing in CX-notation
         xor  dx,dx
         div  cx          ; **** SEE NOTE ****
         push dx
         cmp  ax,0
         je   undo
         call dploop
undo:
         pop  dx
pdig:                     ; Entry-point for printing a small digit in DL
         add  dl,30h
         cmp  dl,39h
         jle  pch
         add  al,7
pch:                      ; Entry-point for printing a single character
         mov  ah,2
         int  21h
         ret
_dpt     ENDP
Note: If you want to be able to print 32-bit numbers, the only thing you'll have to do is replace the line marked with **** SEE NOTE **** with the lines:
         xchg   ax,bx
         div    cx
         xchg   ax,bx
         div    cx
When you enter the procedure the bx:ax pair should contain the 32-bit number you want to print (bx contains the heighest 16 bits).

I even use this procedure in some of my Pascal programs, since it is a fast and easy way to print numbers in Hex, Dec, Oct or Bin at the users wish. Here goes a program that shows the power of the routine:

program Bases;

procedure PrintNumber; assembler;
{ AX must hold the number (word), and
  CX must hold the base. }
asm
@dploop:
  xor  dx,dx
  div  cx
  push dx
  cmp  ax,0
  je   @undo
  call @dploop
@undo:
  pop  dx
@pdig:
  add  dl,30h
  cmp  dl,39h
  jle  @pch
  add  dl,7
@pch:
  mov  ah,2
  int  21h
end;

procedure PrintNum(Number, Base: Word); assembler;
{ PrintNumber interface. }
asm
  mov  ax,Number
  mov  cx,Base
  call PrintNumber
end;

begin
  Write(#13#10'$FFFF hex = ');
  PrintNum($FFFF,$10);
  Write(#13#10'$FFFF dec = ');
  PrintNum($FFFF,10);
  Write(#13#10'$FFFF (9) = ');
  PrintNum($FFFF,9);
  Write(#13#10'$FFFF oct = ');
  PrintNum($FFFF,8);
  Write(#13#10'$FFFF (7) = ');
  PrintNum($FFFF,7);
  Write(#13#10'$FFFF (6) = ');
  PrintNum($FFFF,6);
  Write(#13#10'$FFFF (5) = ');
  PrintNum($FFFF,5);
  Write(#13#10'$FFFF (4) = ');
  PrintNum($FFFF,4);
  Write(#13#10'$FFFF (3) = ');
  PrintNum($FFFF,3);
  Write(#13#10'$FFFF bin = ');
  PrintNum($FFFF,2);
  Writeln;
end.
If you want, you can call the PrintNumber procedure directly in your program, thus saving a timeconsuming procedure-call, ie:
begin
  Writeln('What is 1234h in decimal?');
  Write('ohh, it is: ');
  asm
    mov  ax,1234h
    mov  cx,10
    call PrintNumber
  end;
end.