
IDEAL
MODEL small
STACK 600h
DATASEG
rndstr        db   '$$$$$'
rndnums       db   '02173514869712304859681234605973571204986634127098'    ; for random gen
clock         equ  es:6ch
digs          db   4
rndlimit      equ  50
upper         equ  250
rndupper      dw   ? 
size1         equ  4
vardec        dw   10
CODESEG
;----------------------------------------------------------------------------------------------------+
proc          genrnd                 ;Using the 1/100s of the clock for indexing into a digit string |
;----------------------------------------------------------------------------------------------------+
; Get upper limit and rnd number string as parameters.The proc always creates a 4-digit number based |
; on the clock (1/100s) and a string of digits. 'upper' is the upper limit of the randoms.           |
;----------------------------------------------------------------------------------------------------+
              push bp
              mov  bp,sp
              mov  dx,[bp+4]               ; upper limit for random 
              mov  [rndupper],dx 
              xor  cx,cx
              mov  cl,[byte ptr digs]      ;number of digits = loops for new time reading
              mov  di,offset rndnums
              mov  si,offset rndstr        ;the generated number will be stored here (as a string) 
 rndloop:     push cx                      ;loop to generates one digit. Save it cause clock changes 
              mov  ah,2Ch                  ;ch- hr , cl - min, dh -sec   dl - 1/100s
              int  21h
              mov  bl,rndlimit             ;rndlimit is one more than the largest index generated
              xor  ax,ax
              mov  al,dl                   ;(0 to 99)
              div  bl                      ;ah = ax mod bl   (so ah<50) - length of rndnums is 50
;---------------------------------------------------------------------------------------------------
; Use ah as index into rndnums, picking digits for a random number
;---------------------------------------------------------------------------------------------------
              xor  bx,bx
              mov  bl,ah  
              mov  al,[di+bx]              ;remeber? di points to the beginning of rndnums.
              mov  [si],al                 ;build random number in memory 
              inc  si                      ;si is at the current digit
              push 2                       ;delay by 2 clock cycles (parameter for delay1)
		      call delay1                  ;i.e. if the clock is at: 02:20 (ss:hh) + 0.055*2= 02:31
		      pop  cx
              loop rndloop	
; Turn the string of random (4 digits) into a number limited by the parameter.

              mov  di,offset rndstr        ;prepare for calling strnumber.
              call strnumber               ;dx gets the resulting 4 digit number (converted from str)
              mov  ax,dx
              xor  dx,dx
              mov  bx,[rndupper]
              inc  bx                      ;allow the upper limit to be included.
              div  bx                      ;dx = dx:ax mod bx (The mod is what we want)                             
              pop  bp
              ret  2
endp          genrnd
;---------------------------------------------------------------------------------------------------
proc          delay1               ; delays execution by 'parameter' * 1/18th of a second
; Used by genrnd to wait for couple of tics, in order for the random to be                 
; better. (one parm - delay amount). Each tic is 1/18th of a second. 
              push bp
              mov  bp,sp 
              xor  cx,cx
              mov  cx,[bp+4]               ;delay amount as parameter
              mov  ax,40h
              mov  es,ax                                                                        
tick:         mov  ax,[clock]
notick:       cmp  ax,[clock]              ; Wait for a clock tic
              je   notick               
              loop tick 
              pop  bp
              ret  2           
endp          delay1
;-----------------------------------------------------------------------------------------------------
proc          strnumber
;  Uses a memory location loaded into di by the calling module, to get a string of          
;  numbers (in ASCII), and turns it into a number placed in dx.   
;
;count how many digits we have
              xor  ax,ax
              xor  bx,bx
              push di
countloop:     
              mov  bl,[di]
              cmp  bl,'$'
              je   updatesize
              inc  al
              inc  di
              jmp  countloop
updatesize:
              pop  di
              mov  [size1],al
              xor  cx,cx
              mov  cl,[size1]
              mov  bx,1
              xor  dx,dx
              xor  ax,ax
              add  di,cx
              sub  di,1
loop1:              
              mov  al,[di] 
              mov  ah,0
              sub  al,30h
              push dx 
              mul  bx
              pop  dx 
              add  dx,ax
              mov  ax,bx
              push dx
              mul  [vardec]
              pop  dx 
              mov  bx,ax
              dec  di
              loop loop1 
              ret
endp          strnumber              
;-----------------------------------------------------------------------------------------------------
start:        mov  ax,@data
              mov  ds,ax  
              mov  ax,upper  
              push ax            
              call genrnd                   ; places random in dx
;-----------------------------------------------------------------------------------------------------                                 	                 
exit:         mov  ax, 4c00h
              int  21h
END start              