home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Troubleshooting Netware Systems
/
CSTRIAL0196.BIN
/
attach
/
pcc
/
v08n03
/
math.exe
/
SHUFFLE2.ZIP
/
SHUFFLE2.ASM
next >
Wrap
Assembly Source File
|
1992-12-03
|
9KB
|
403 lines
;SHUFFLE - Output any set of up to 32K (almost) numbers
;
;Thanks to David Wesson, PhD, and his SHUFFLE.C for the idea.
;See SHUFFLE2.DOC for details, discussion, etc.
;
;v1.0 3 Dec 92 Initial release
;
;Released to the public domain
;David Kirschbaum
;Toad Hall
;kirsch@sesi.com
CR EQU 0DH
LF EQU 0AH
STDOUT EQU 1
STDERR EQU 2
CSEG SEGMENT PUBLIC PARA 'Code'
ASSUME CS:CSEG,DS:CSEG
BeginDump EQU $ ;for computing program size
ORG 100H ;.COM program
Shuffle PROC NEAR
jmp short Start
y db 12 ;number counter for CR/LF
count dw 0
upper dw 0
Start: call Init ;Initialize everything
;(all the procedures that'll be
;overwritten by our array)
;DI = lower
mov si,count ;handy for testing
xor ax,ax ;init x=0
mov bx,offset array
InitLup:
mov bx,ax ;x
shl bx,1 ;*2 for words
mov array[bx+2],di ;=lower
inc di ;lower++
inc ax ;x++
cmp ax,si ;count ;did "count" bitbuckets?
jb InitLup ;not yet
;Now use SI as X. Start with "count"
CountLup:
call Rand ;get random number in AX
cwd ;convert to doubleword
idiv si ;MOD x
inc dx ;mod is in DX, bump
mov bx,dx ;num
shl bx,1 ;*2 for words
add bx,offset array ;^array[num]
push bx ;save array[num] ptr for later
mov ax,[bx] ;array[num]^
call ItoA ;convert, write to STDOUT
mov bx,si ;x
shl bx,1 ;*2 for words
mov ax,array[bx] ;array[x]
pop bx ;BX -> array[num]
mov [bx],ax ;array[num] = array[x]
mov ah,1 ;check kbd status
int 16H ;via BIOS
jnz Exit ;keypressed, interrupted, halt.
dec si ;x--
jnz CountLup ;not zeroed yet
Exit: mov ax,4C00H ;terminate, ERRORLEVEL 0
int 21H
Shuffle ENDP
PAD EQU 6 ;left-padded to 6 spaces
nrstr db PAD dup(20H) ;work area to build integers
LASTNR EQU $-1 ;last digit in work area
db CR,LF
ItoA PROC NEAR
push di ;save upper
std ;we're going backwards
mov cx,PAD ;constant chars long
mov di,offset LASTNR ;last char in work area
mov bx,10 ; bx = divisor
ItoA10: or ax, ax ; q. any value to convert?
jz ItoA20 ; a. no .. exit loop
xor dx,dx ; dx:ax = value to divide
idiv bx ;10 ; ax = dividend, dx = remainder
or dl,30H ; dl = ASCII number
mov [di],dl ; store character in buffer
dec di ; di -> next output char location
dec cx ; q. any more room in buffer?
jnz ItoA10 ; a. yes .. continue loop
jmp short ItoA90 ;exit
ItoA20: mov al,20H ;space fill char
ItoA30: stosb ; store fill character
dec cx ; q. any more room in buffer?
jnz ItoA30 ; a. yes .. continue loop
ItoA90: cld ;insure fwd again (to be neat)
;Do our displaying right here,
;to include wrap-around
mov dx,offset nrstr ;Ascii number string
mov cx,PAD ;5 chars
dec y ;decrement number counter
jnz NotYet ;11..0
mov cx,PAD+2 ;include CR,LF
mov y,12 ;back to 12
NotYet:
mov bx,STDOUT ;stdout handle
mov ah,40H ;write to file/device
int 21H
pop di ;restore
ret
ItoA ENDP
;Area: `PC Assembly Language' Date: 28 Oct 92 23:08:02
;From: Lou Ciriello To: All
;Subj: Random number generator
;
;Borland decided the following random number generator worthy of including
;within their TURBO-C 2.0 small model library:
;v1.1 Toad Hall Tweak
w1 DW 0A4F8h
w2 DW 028C9h
; RAND - Computes a pseudo-random number from 0 to 32,767 in AX
Rand PROC NEAR
push si ;save 'x'
MOV CX,015Ah
MOV BX,04E35h
mov si,w2
mov ax,w1
mov dx,ax
MUL BX ;const2
XCHG AX,CX
MUL SI
ADD CX,AX
MOV AX,SI
MUL BX ;const2
ADD DX,CX
ADD AX,1
ADC DX,0
MOV w2,AX
MOV AX,DX ;random nr into AX
mov w1,ax ;save for next time's seed
and ax,07FFH ;mask to 8-bit
pop si ;restore 'x'
RET
Rand ENDP
;Our array will start here, overwriting any startup code
;to save space.
even
array label word
EndDump EQU $ ;for computing program size
s120 db 'Hit any key to ABORT.',CR,LF
s120LEN EQU $-s120
Init PROC NEAR
call GetArgs ;get lower, upper values
;(may die)
;Initialize our random number generator.
call Srand ;initialize random nr generator seed
mov dx,offset s120 ;'Hit any key to abort'
mov cx,s120LEN ;msg length
mov bx,STDERR ;only to screen
mov ah,40H ;write to file/device
int 21H
ret
Init ENDP
s0 db 'SHUFFLE randomizes a range of numbers specified '
db 'as lower and upper',CR,LF
s67 db 'Syntax: SHUFFLE lower upper',CR,LF,'$'
errmsg db 'Difference between higher and lower is too large.',CR,LF,'$'
s95 db 'Maximum range is $'
GetArgs PROC NEAR
mov si,80H ;PSP cmdline
xor ax,ax ;clear msb
lodsb
mov cx,ax ;into cx
jcxz BadArg ;0, return CF set
call FindArg ;get argv[1]
jc BadArg ;bummer, hit CR. Insufficient parms
;We have a legal digit. SI -> that digit.
call AtoI ;convert to integer
mov di,ax ;save as lower (always in DI)
;SI should be pointing to just past the separating space.
;No guarantee it'll be the next integer, however.
call FindArg ;get argv[2]
jc BadArg ;bummer, hit CR, no argv[2]
;SI -> second argument
call AtoI ;convert argv[2] to integer
mov upper,ax ;save it
;count = upper-lower+1
sub ax,di ;-lower
jbe BadArg ;upper should be bigger than lower
inc ax ;+1
mov count,ax ;count
;Is count bigger than we have array space for?
call FreeSpace ;returns words free in AX
cmp ax,count ;enough room?
jb NoRoom ;nope
ret ;with lower in DI
NoRoom:
mov dx,offset errmsg ;'Too big'
jmp short MsgTerm
BadArg: mov dx,offset s0 ;usage msg
MsgTerm:
mov ah,9 ;display msg
int 21H
mov dx,offset s95 ;'Max range is ...'
mov ah,9 ;display msg
int 21H
call FreeSpace ;words free in AX
mov y,1 ;so it'll zero out and produce CR/LF
call ItoA ;display
mov ax,4C01H ;terminate, ERRORLEVEL 1 v1.1
int 21H
GetArgs ENDP
FindArg PROC NEAR
lodsb ;get char
cmp al,CR ;terminating CR?
jz NoArg ;yep
cmp al,'0' ;we only want 0..9
jb FindArg ;nope, ignore
cmp al,'9'
ja FindArg ;ignore
;AL has first 0..9 char.
dec si ;back SI back up to that char
clc ;return CF clear
ret
NoArg: stc
ret
FindArg ENDP
;Compute available free space in code segment (beyond runtime code).
;Program size (EndDump-BeginDump)
;Stack 100H
FreeSpace PROC NEAR
mov ax,((EndDump-BeginDump) + 100H) ;prog size
neg ax ;flip, produces remaining bytes
shr ax,1 ;/2 for words
ret
FreeSpace ENDP
;From CONVERT.ASM
;----------------------------------------------------------------------
; INPUT: DS:SI points to parameter start
; OUTPUT: AX = number; CY = 0 if valid entry; CY = 1 if invalid entry.
;----------------------------------------------------------------------
ten dw 10 ;constant for multiplying
AtoI PROC NEAR
xor bx,bx ;init "accumulator" BX
Next_Decimal:
lodsb ;Get a character.
sub al,'0' ;ASCII to binary.
jc End_Decimal ;If not between 0 and 9, we're done
cmp al,9
ja End_Decimal
cbw ;Convert to word.
xchg ax,bx ;Swap old and new number.
mul ten ;shift to left by multiplying
; last entry by 10
jc End_Decimal ;If carry, too big.
add bx,ax ;Add new number and store in BX.
jc Overflow ;if carry, too big
Loop_Decimal:
jmp Next_Decimal
End_Decimal:
mov ax,bx ;return in AX
clc ;return CF clear
ret
Overflow:
mov ax,bx ;return in AX
stc ;return CF set
ret
AtoI ENDP
Srand PROC NEAR
;Note: While this is not a verbatim disassembly, it produces the same sequence
;of numbers as Borland's random number generator for a given seed.
;[Break to yet another message for the initial seed]
;Area: `PC Assembly Language' Date: 12 Oct 92 22:37:00
;From: Nick Downing To: All
;Subj: Random numbers
;
;For people interested in generating random numbers, a great way to get a
;"seed" is this:
CLI
IN AL,40H
MOV AH,AL
STI
IN AL,40H
;The effect is to read the 1.19318MHz system clock. This 16-bit value is
;incremented (you guessed) 1193180 times a second, which makes it pretty random.
; It wraps around from 65536 to 0. That bit of code, by the way, gives you the
;low order of the system clock in AH, and the high order in AL. This byte
;reversal makes the numeric value even more random (and saves two bytes of code
;:).
;
;Oh, and in case you were wondering, the reason for the STI being the
;second-last instruction rather than the last, is that after an STI interrupts
;aren't disabled till the end of the next instruction (a defined and documented
;feature of the chip).
;
;Cheers,
;Mic
;-!- FMail 0.92
; ! Origin: The Gate - Melbourne, Australia - +61-3-879-9082 (3:633/159)
;[And back to the Ciriello code again]
;SRAND - Seeds the random number generator with the value in AX. If AX is null
; the low order word of the number of clock ticks since midnight is used
or ax,ax ;0? v1.1
jnz Srand1
int 1AH
mov ax,dx
Srand1: mov w1,0 ;v1.1
mov w2,ax
ret
Srand ENDP
CSEG ENDS
END Shuffle