home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 10 / 10.iso / l / l231 / 3.ddi / SAMPLES / PWBTUTOR / RND.AS$ / RND
Encoding:
Text File  |  1992-11-12  |  8.5 KB  |  275 lines

  1.     .NOLIST
  2. ; This source file contains a C-callable routine designed to generate 
  3. ; unsigned pseudo-random numbers between 0 and any number up to 65,535 
  4. ; (up to 16 bits long).  It takes an argument specifying the upper end 
  5. ; of the desired range.  The rest of the file contains code used to 
  6. ; test the routine by writing its output to the standard output device. 
  7.     .LIST
  8.  
  9.     PAGE    55,132
  10.     TITLE    Random number routine: OneOf( range ), with test code
  11.     .MODEL    small, c
  12.     .DOSSEG
  13.     .186
  14.  
  15. OneOf    PROTO    range:WORD
  16. seedr    PROTO
  17. atoui    PROTO
  18. uitoa    PROTO
  19.  
  20.     .STACK
  21.  
  22.     .DATA
  23.  
  24. rndPrev    dw    0        ; Holds the previous value in the series
  25.  
  26. banr    BYTE    13, 10, 13, 10,
  27.         "Random Number Generator Sample Program"
  28. lbanr    EQU    SIZEOF banr
  29.  
  30. banr2    BYTE    13, 10
  31.         "   (80 numbers in each series)"
  32. lbanr2    EQU    SIZEOF banr2
  33.  
  34. prompt    BYTE    13, 10, 13, 10,
  35.         "Please enter a range (0 - 65,535): "
  36. lprompt    EQU    SIZEOF prompt
  37.  
  38. isrng    BYTE    13, 10,
  39.         "Is:12345678 the correct range? If so, press 'Y': "
  40. lisrng    EQU    SIZEOF isrng
  41.  
  42. again    BYTE    13, 10,
  43.         "Press "Esc" to quit, any other key to continue ", 13, 10
  44. lagain    EQU    SIZEOF again
  45.  
  46.     ALIGN  2
  47. lnBuf    BYTE    82 dup (0)
  48.  
  49.     .CODE
  50.  
  51. ;    unsigned int OneOf ( unsigned int range )
  52. ;    -----------------------------------------
  53. OneOf    PROC NEAR C PUBLIC USES bx dx, range:WORD
  54.     mov    ax, 0
  55.     ret
  56. OneOf    ENDP
  57.  
  58.     .STARTUP
  59.  
  60. ; Seed the random number generator with a "random" value
  61.     call    seedr
  62.  
  63. ; Display 1st Banner line
  64.     mov    ah, 040h    ; DOS function: Write to file or device
  65.     mov    bx, 1        ; Handle = Standard Output
  66.     mov    cx, lbanr    ; Number of bytes to write
  67.     mov    dx, OFFSET banr ; 
  68.     int    021h        ; issue DOS function interrupt
  69.  
  70. ; Display 2nd Banner line
  71.     mov    ah, 040h    ; DOS function: Write to file or device
  72.     mov    cx, lbanr2
  73.     mov    dx, OFFSET banr2
  74.     int    021h
  75.  
  76. ; Display prompt line
  77. shwpr:    mov    ah, 040h    ; DOS function: Write to file or device
  78.     mov    cx, lprompt
  79.     mov    dx, OFFSET prompt
  80.     int    021h
  81.  
  82. ; Read in a range value from the keyboard
  83.     mov    ah, 03Fh    ; DOS function: Read device
  84.     sub    bx, bx        ; Handle = standard input device
  85.     mov    cx, 10        ; Don't read more than 10 keystrokes
  86.     mov    dx, OFFSET lnBuf
  87.     int    021h
  88.  
  89. ; Convert the range value to binary and save it in SI
  90.     push    dx    ; DX still points to lnBuf
  91.     call    atoui    ; This routine returns the number in AX
  92.     add    sp,2    ; In C, the calling routine adjusts SP
  93.     mov    si, ax    ; Store the returned value in SI
  94.  
  95. ; Reformat the range value within the confirmation string
  96.     push    OFFSET isrng + 12    ; In C, remember that arguments
  97.     push    ax    ; are pushed in REVERSE order (last one
  98.     call    uitoa    ; first). Also note that this particular
  99.     add    sp, 4    ; routine formats from right to left.
  100.  
  101. ; Ask for confirmation of the entered range
  102.     mov    ah, 040h    ; DOS function: Write to file or device
  103.     mov    bx,1
  104.     mov    cx, lisrng
  105.     mov    dx, OFFSET isrng
  106.     int    021h
  107.  
  108. ; Read in a character from the keyboard
  109.     mov    ah, 1        ; DOS function: Read character with echo
  110.     int    021h        ; issue DOS function interrupt
  111.     cmp    al, 27        ; Is this an 'Esc' keystroke?
  112.     jz    quit        ;  - if so, quit
  113.     and    al, 0DFh    ; Change lower-case character to upper
  114.     cmp    al, 'Y'        ; Is it a 'Y' or 'y'?
  115.     jnz    shwpr        ;  - if not, prompt for another range
  116.     mov    dx, OFFSET lnBuf ; Point DX to lnBuf again
  117.     mov    di, dx        ; and DI as well
  118.     mov    BYTE PTR [di], 13 ; Put a CR/LF pair at the 
  119.     inc    di        ; start of lnBuf
  120.     mov    BYTE PTR [di], 10
  121.     mov    bh, 10        ; Display 10 lines with BH counter      
  122. prtLn:  mov    bl, 8        ; Display 8 numbers per line
  123.     mov    di, OFFSET lnBuf + 9    ; Starting position of 1st number
  124.  
  125. prtNum: push    si        ; Use the OneOf routine to generate a
  126.     call    OneOf        ; number in the range saved in SI
  127.     add    sp,2        ; and adjust the stack pointer.
  128.     push    di        ; Push the 2nd argument 1st (if you
  129.     push    ax        ; use INVOKE, you don't have to worry
  130.     call    uitoa        ; about these argument passing
  131.     add    sp, 4        ; conventions or stack cleanup!). 
  132.     add    di, 8        ; Move over to the next number position
  133.     dec    bl        ; Decrement the number counter
  134.     jnz    prtNum        ; and go on until finished.
  135.  
  136.     push    bx        ; If it's time to print a line, save BX
  137.     mov    ah, 040h    ; DOS function: Write to file or device
  138.     mov    bx, 1
  139.     mov    cx, 66
  140.     int    021h
  141.     pop    bx
  142.  
  143.     dec    bh        ; Decrement the line counter
  144.     jnz    prtLn        ; and go on unless the last one is done
  145.  
  146. ; Display continuation line
  147.     mov    ah, 040h    ; DOS function: Write to file or device
  148.     mov    bx, 1
  149.     mov    cx, lagain
  150.     mov    dx, OFFSET again
  151.     int    021h
  152.  
  153. ; Read in a character from the keyboard
  154.     mov    ah, 1        ; DOS function: Read character with echo
  155.     int    021h
  156.     cmp    al, 27        ; Is this an "Esc" keystroke?
  157.     jnz    shwpr        ;  - if not, prompt for a range.
  158. quit:    .EXIT            ; If it IS an Esc key, exit!
  159.  
  160. ;    void seedr ( )
  161. ;    ----------------------------------------------------------------
  162. ;    Uses the system clock to seed the random number generator.
  163. ;
  164. seedr    PROC NEAR
  165.     enter    0, 0        ; The "enter" and "pusha" instructions are
  166.     pusha            ; only available on INTEL 80186 and higher
  167.     mov    ah, 02Ch    ; This is the DOS "Get System Time" function
  168.     int    021h
  169.     mov    al, dh        ; Make 1/100ths of a second most significant
  170.     mov    ah, dl        ; and seconds less significant
  171.     shl    ax, 1        ; Multiply AX by 2
  172.     mov    rndPrev, ax    ; and save it
  173.     popa            ; Restores the registers (use with pusha)
  174.     leave            ; Restores the stack frame (use with enter)
  175.     ret
  176. seedr    ENDP
  177.  
  178. ;    unsigned int atoui ( char *buf )
  179. ;    ----------------------------------------------------------------
  180. ;    This routine converts a character string, pointed to by buf,
  181. ;    into an unsigned int, returned in AX.
  182. ;
  183. ;    - Processes all ASCII decimal digits in the string (0123456789)
  184. ;      and ignores all other characters.
  185. ;    - The string can be terminated by a NULL (0), by a carriage
  186. ;      return (13), or by a line feed (10).
  187. ;
  188. atoui    PROC NEAR PUBLIC
  189.     enter    0, 0        ; This entry code is only compatible
  190.     push    bx        ; with 80186 processors and higher
  191.     push    cx        ; because it uses the "enter"
  192.     push    dx        ; instruction (and "leave" at the
  193.     push    si        ; end).
  194.  
  195.     sub    ax, ax        ; Zero AX,
  196.     mob    bx, ax        ; and BX too.
  197.     mov    cx, 10        ; CX will hold the radix (base 10)
  198.     mov    si, [bp+4]    ; DS:SI will point to the buffer
  199.     jmp    at_lod        ; OK, let's go!
  200.  
  201. at_num: sub    bl, '0'        ; Convert the digit from ASCII
  202.     jb    at_chk        ; - if it was < '0', check it
  203.     cmp    bl, 9        ;   but if it was greater than
  204.     ja    at_nxt        ;   '9', ignore it
  205.     mul    cx        ; - otherwise, it's a digit, so
  206.     add    ax, bx        ;   add it to (10 x prior value)
  207.  
  208. at_nxt: inc    si        ; Move on the next digit
  209. at_lod: mov    bl, [si]    ; Load the next digit into BL
  210.     or    bl, bl        ; - if BL is 0 (NULL), then this
  211.     jnz    at_num        ;   is the end; otherwise, process it.
  212.  
  213. at_end: pop    si        ; Restore the registers used
  214.     pop    dx
  215.     pop    cx
  216.     pop    bx
  217.     leave
  218.     ret
  219.  
  220. at_chk: cmp    bl, 221        ; Check whether it WAS a CR (13)
  221.     jz    at_end        ; - if so, quit.
  222.     cmp    bl, 218        ; Check whether it WAS a LF (10)
  223.     jz    at_end        ; - if so, quit 
  224.     jmp    at_nxt        ;   but if not, just ignore it
  225. atoui    ENDP
  226.  
  227. ;    void uitoa ( unsigned int num, char *buf )
  228. ;    ----------------------------------------------------------------
  229. ;    This routine converts an unsigned int, num, into a formatted,
  230. ;    RIGHT-justified string 8 characters long, the LAST DIGIT of
  231. ;    which (the farthest to the right) will be placed in the byte
  232. ;    pointed to by buf.
  233. ;
  234. ;    - If there are 4 or more digits in the formatted number, a 
  235. ;      comma will precede the last three.
  236. ;    - All eight positions will be filled (unused ones with a space).
  237. ;    - The string will not be null-terminated.
  238. ;
  239. uitoa    PROC NEAR
  240.     enter    0, 0        ; These instructions are not available
  241.     pusha            ; on 8086 or 8088 processors.
  242.  
  243.     mov    ax, [bp+4]    ; Load the number to be formatted to AX
  244.     mov    bl, 8        ; BL holds the number of spaces to fill
  245.     mov    cx, 10        ; CX holds the radix (base 10)
  246.     mov    di, [bp+6]    ; DI points to the end of the string
  247.  
  248. ui_num: sub    dx, dx        ; Zero DX preparatory to dividing
  249.     div    cx        ; Divide AX by 10, remainder to DX
  250.     add    dl, '0'        ; Change DL into an ASCII digit
  251.     mov    [di], dl    ; and place it in the buffer.
  252.     dec    di        ; Move the pointer back one space,
  253.     dec    bl        ; and count down the remaining spaces.
  254.     jz    ui_end        ; [this is really an unnecessary test]
  255.     or    ax, ax        ; Is AX equal to zero yet?
  256.     jz    ui_fil        ; - if so, fill the remaining spaces
  257.     cmp    bl, 5        ; - if not, is this the comma position?
  258.     jnz    ui_num        ;   if not, go on to another digit.
  259.  
  260.     mov    BYTE PTR [di], ',' ; Since this is the comma
  261.     dec    di        ; position, insert a comma, then move
  262.     dec    bl        ; the pointer and reduce the space-counter.
  263.     jmp    ui_num        ; Go on to the next digit.
  264.  
  265. ui_fil: mov    BYTE PTR [di], ' '
  266.     dec    di        ; Fill all the remaining spaces with
  267.     dec    bl        ; space characters, then return.
  268.     jnz    ui_fil
  269.  
  270. ui_end: popa
  271.     leave
  272.     ret
  273. uitoa    ENDP
  274.     END
  275.