home *** CD-ROM | disk | FTP | other *** search
/ Troubleshooting Netware Systems / CSTRIAL0196.BIN / attach / pcc / v08n03 / math.exe / SHUFFLE2.ZIP / SHUFFLE2.ASM next >
Assembly Source File  |  1992-12-03  |  9KB  |  403 lines

  1. ;SHUFFLE    - Output any set of up to 32K (almost) numbers
  2. ;
  3. ;Thanks to David Wesson, PhD, and his SHUFFLE.C for the idea.
  4. ;See SHUFFLE2.DOC for details, discussion, etc.
  5. ;
  6. ;v1.0    3 Dec 92  Initial release
  7. ;
  8. ;Released to the public domain
  9. ;David Kirschbaum
  10. ;Toad Hall
  11. ;kirsch@sesi.com
  12.  
  13. CR    EQU    0DH
  14. LF    EQU    0AH
  15. STDOUT    EQU    1
  16. STDERR    EQU    2
  17.  
  18. CSEG    SEGMENT PUBLIC PARA 'Code'
  19.     ASSUME    CS:CSEG,DS:CSEG
  20. BeginDump    EQU    $        ;for computing program size
  21.  
  22.     ORG    100H            ;.COM program
  23.  
  24. Shuffle    PROC    NEAR
  25.  
  26.     jmp    short Start
  27.  
  28. y    db    12            ;number counter for CR/LF
  29. count    dw    0
  30. upper    dw    0
  31.  
  32. Start:    call    Init            ;Initialize everything
  33.                     ;(all the procedures that'll be
  34.                     ;overwritten by our array)
  35. ;DI = lower
  36.  
  37.     mov    si,count        ;handy for testing
  38.     xor    ax,ax            ;init x=0
  39.     mov    bx,offset array
  40. InitLup:
  41.     mov    bx,ax            ;x
  42.     shl    bx,1            ;*2 for words
  43.     mov    array[bx+2],di        ;=lower
  44.     inc    di            ;lower++
  45.     inc    ax            ;x++
  46.     cmp    ax,si    ;count        ;did "count" bitbuckets?
  47.     jb    InitLup            ;not yet
  48.  
  49. ;Now use SI as X.  Start with "count"
  50.  
  51. CountLup:
  52.     call    Rand            ;get random number in AX
  53.     cwd                ;convert to doubleword
  54.     idiv    si            ;MOD x
  55.     inc    dx            ;mod is in DX, bump
  56.  
  57.     mov    bx,dx            ;num
  58.     shl    bx,1            ;*2 for words
  59.     add    bx,offset array        ;^array[num]
  60.     push    bx            ;save array[num] ptr for later
  61.  
  62.     mov    ax,[bx]            ;array[num]^
  63.     call    ItoA            ;convert, write to STDOUT
  64.  
  65.     mov    bx,si            ;x
  66.     shl    bx,1            ;*2 for words
  67.     mov    ax,array[bx]        ;array[x]
  68.  
  69.     pop    bx            ;BX -> array[num]
  70.     mov    [bx],ax            ;array[num] = array[x]
  71.  
  72.     mov    ah,1            ;check kbd status
  73.     int    16H            ;via BIOS
  74.     jnz    Exit            ;keypressed, interrupted, halt.
  75.  
  76.     dec    si            ;x--
  77.     jnz    CountLup        ;not zeroed yet
  78.  
  79. Exit:    mov    ax,4C00H    ;terminate, ERRORLEVEL 0
  80.     int    21H
  81.  
  82. Shuffle    ENDP
  83.  
  84. PAD    EQU    6        ;left-padded to 6 spaces
  85.  
  86. nrstr    db    PAD dup(20H)    ;work area to build integers
  87. LASTNR    EQU    $-1        ;last digit in work area
  88.     db    CR,LF
  89.  
  90. ItoA    PROC    NEAR
  91.  
  92.     push    di            ;save upper
  93.     std                 ;we're going backwards
  94.  
  95.     mov    cx,PAD            ;constant chars long
  96.     mov    di,offset LASTNR    ;last char in work area
  97.  
  98.     mov    bx,10            ; bx = divisor
  99.  
  100. ItoA10:    or    ax, ax            ; q. any value to convert?
  101.     jz    ItoA20            ; a. no .. exit loop
  102.  
  103.     xor    dx,dx            ; dx:ax = value to divide
  104.     idiv    bx    ;10        ; ax = dividend, dx = remainder
  105.     or    dl,30H            ; dl = ASCII number
  106.     mov    [di],dl            ; store character in buffer
  107.     dec    di            ; di -> next output char location
  108.  
  109.     dec    cx            ; q. any more room in buffer?
  110.     jnz    ItoA10            ; a. yes .. continue loop
  111.  
  112.     jmp    short ItoA90        ;exit
  113.  
  114. ItoA20:    mov    al,20H            ;space fill char
  115. ItoA30:    stosb                ; store fill character
  116.  
  117.     dec    cx            ; q. any more room in buffer?
  118.     jnz    ItoA30            ; a. yes .. continue loop
  119.  
  120. ItoA90:    cld                ;insure fwd again (to be neat)
  121.  
  122. ;Do our displaying right here,
  123. ;to include wrap-around
  124.  
  125.     mov    dx,offset nrstr        ;Ascii number string
  126.     mov    cx,PAD            ;5 chars
  127.     dec    y            ;decrement number counter
  128.     jnz    NotYet            ;11..0
  129.      mov    cx,PAD+2        ;include CR,LF
  130.      mov    y,12            ;back to 12
  131. NotYet:
  132.     mov    bx,STDOUT        ;stdout handle
  133.     mov    ah,40H            ;write to file/device
  134.     int    21H
  135.  
  136.     pop    di            ;restore
  137.     ret
  138.  
  139. ItoA    ENDP
  140.  
  141.  
  142. ;Area: `PC Assembly Language'    Date: 28 Oct 92  23:08:02
  143. ;From: Lou Ciriello        To: All
  144. ;Subj: Random number generator
  145. ;
  146. ;Borland decided the following random number generator worthy of including
  147. ;within their TURBO-C 2.0 small model library:
  148.  
  149. ;v1.1 Toad Hall Tweak
  150.  
  151. w1    DW    0A4F8h
  152. w2    DW    028C9h
  153.  
  154. ; RAND - Computes a pseudo-random number from 0 to 32,767 in AX
  155.  
  156. Rand    PROC    NEAR
  157.     push    si            ;save 'x'
  158.  
  159.     MOV    CX,015Ah
  160.     MOV    BX,04E35h
  161.     mov    si,w2
  162.     mov    ax,w1
  163.     mov    dx,ax
  164.     MUL    BX            ;const2
  165.     XCHG    AX,CX
  166.     MUL    SI
  167.     ADD    CX,AX
  168.     MOV    AX,SI
  169.     MUL    BX            ;const2
  170.     ADD    DX,CX
  171.     ADD    AX,1
  172.     ADC    DX,0
  173.     MOV    w2,AX
  174.     MOV    AX,DX            ;random nr into AX
  175.     mov    w1,ax            ;save for next time's seed
  176.     and    ax,07FFH        ;mask to 8-bit
  177.  
  178.     pop    si            ;restore 'x'
  179.     RET
  180. Rand    ENDP
  181.  
  182.  
  183. ;Our array will start here, overwriting any startup code
  184. ;to save space.
  185.  
  186.     even
  187. array    label    word
  188. EndDump    EQU    $            ;for computing program size
  189.  
  190. s120    db    'Hit any key to ABORT.',CR,LF
  191. s120LEN    EQU    $-s120
  192.  
  193. Init    PROC    NEAR
  194.  
  195.     call    GetArgs            ;get lower, upper values
  196.                     ;(may die)
  197.  
  198. ;Initialize our random number generator.
  199.     call    Srand            ;initialize random nr generator seed
  200.  
  201.     mov    dx,offset s120        ;'Hit any key to abort'
  202.     mov    cx,s120LEN        ;msg length
  203.     mov    bx,STDERR        ;only to screen
  204.     mov    ah,40H            ;write to file/device
  205.     int    21H
  206.  
  207.     ret
  208. Init    ENDP
  209.  
  210.  
  211. s0    db    'SHUFFLE randomizes a range of numbers specified '
  212.     db    'as lower and upper',CR,LF
  213. s67    db    'Syntax: SHUFFLE lower upper',CR,LF,'$'
  214.  
  215. errmsg    db    'Difference between higher and lower is too large.',CR,LF,'$'
  216.  
  217. s95    db    'Maximum range is $'
  218.  
  219. GetArgs    PROC    NEAR
  220.     mov    si,80H        ;PSP cmdline
  221.     xor    ax,ax        ;clear msb
  222.     lodsb
  223.     mov    cx,ax        ;into cx
  224.     jcxz    BadArg        ;0, return CF set
  225.  
  226.     call    FindArg        ;get argv[1]
  227.     jc    BadArg        ;bummer, hit CR.  Insufficient parms
  228.  
  229. ;We have a legal digit.  SI -> that digit.
  230.     call    AtoI        ;convert to integer
  231.     mov    di,ax        ;save as lower (always in DI)
  232.  
  233. ;SI should be pointing to just past the separating space.
  234. ;No guarantee it'll be the next integer, however.
  235.  
  236.     call    FindArg        ;get argv[2]
  237.     jc    BadArg        ;bummer, hit CR, no argv[2]
  238.  
  239. ;SI -> second argument
  240.     call    AtoI        ;convert argv[2] to integer
  241.     mov    upper,ax    ;save it
  242.  
  243. ;count = upper-lower+1
  244.  
  245.     sub    ax,di            ;-lower
  246.     jbe    BadArg            ;upper should be bigger than lower
  247.     inc    ax            ;+1
  248.     mov    count,ax        ;count
  249.  
  250. ;Is count bigger than we have array space for?
  251.     
  252.     call    FreeSpace        ;returns words free in AX
  253.     cmp    ax,count        ;enough room?
  254.     jb    NoRoom            ;nope
  255.     ret                ;with lower in DI
  256.  
  257. NoRoom:
  258.     mov    dx,offset errmsg    ;'Too big'
  259.     jmp    short MsgTerm
  260.  
  261. BadArg:    mov    dx,offset s0        ;usage msg
  262.  
  263. MsgTerm:
  264.     mov    ah,9            ;display msg
  265.     int    21H
  266.  
  267.     mov    dx,offset s95        ;'Max range is ...'
  268.     mov    ah,9            ;display msg
  269.     int    21H
  270.  
  271.     call    FreeSpace        ;words free in AX
  272.     mov    y,1            ;so it'll zero out and produce CR/LF
  273.     call    ItoA            ;display
  274.  
  275.     mov    ax,4C01H        ;terminate, ERRORLEVEL 1    v1.1
  276.     int    21H
  277.  
  278.  
  279. GetArgs    ENDP
  280.  
  281.  
  282. FindArg    PROC    NEAR
  283.     lodsb            ;get char
  284.     cmp    al,CR        ;terminating CR?
  285.     jz    NoArg        ;yep
  286.     cmp    al,'0'        ;we only want 0..9
  287.     jb    FindArg        ;nope, ignore
  288.     cmp    al,'9'
  289.     ja    FindArg        ;ignore
  290.  
  291. ;AL has first 0..9 char.
  292.     dec    si        ;back SI back up to that char
  293.     clc            ;return CF clear
  294.     ret
  295.  
  296. NoArg:    stc
  297.     ret
  298. FindArg    ENDP
  299.  
  300.  
  301. ;Compute available free space in code segment (beyond runtime code).
  302. ;Program size    (EndDump-BeginDump)
  303. ;Stack        100H
  304.  
  305. FreeSpace    PROC    NEAR
  306.     mov    ax,((EndDump-BeginDump) + 100H)    ;prog size
  307.     neg    ax            ;flip, produces remaining bytes
  308.     shr    ax,1            ;/2 for words
  309.     ret
  310. FreeSpace    ENDP
  311.  
  312.  
  313. ;From CONVERT.ASM
  314. ;----------------------------------------------------------------------
  315. ; INPUT:  DS:SI points to parameter start
  316. ; OUTPUT: AX = number; CY = 0 if valid entry; CY = 1 if invalid entry.
  317. ;----------------------------------------------------------------------
  318. ten    dw    10            ;constant for multiplying
  319.  
  320. AtoI    PROC    NEAR
  321.     xor    bx,bx            ;init "accumulator" BX
  322. Next_Decimal:
  323.     lodsb                ;Get a character.
  324.     sub    al,'0'            ;ASCII to binary.
  325.     jc    End_Decimal        ;If not between 0 and 9, we're done
  326.     cmp    al,9
  327.     ja    End_Decimal
  328.  
  329.     cbw                ;Convert to word.
  330.     xchg    ax,bx            ;Swap old and new number.
  331.     mul    ten            ;shift to left by multiplying
  332.                     ; last entry by 10
  333.     jc    End_Decimal        ;If carry, too big.
  334.      add    bx,ax            ;Add new number and store in BX.
  335.      jc    Overflow        ;if carry, too big
  336.  
  337. Loop_Decimal:
  338.     jmp    Next_Decimal
  339.  
  340. End_Decimal:
  341.     mov    ax,bx            ;return in AX
  342.     clc                ;return CF clear
  343.     ret
  344. Overflow:
  345.     mov    ax,bx            ;return in AX
  346.     stc                ;return CF set
  347.     ret
  348. AtoI    ENDP
  349.  
  350.  
  351. Srand    PROC    NEAR
  352. ;Note:  While this is not a verbatim disassembly, it produces the same sequence
  353. ;of numbers as Borland's random number generator for a given seed.
  354.  
  355. ;[Break to yet another message for the initial seed]
  356. ;Area: `PC Assembly Language'    Date: 12 Oct 92  22:37:00
  357. ;From: Nick Downing        To: All
  358. ;Subj: Random numbers
  359. ;
  360. ;For people interested in generating random numbers, a great way to get a
  361. ;"seed" is this:
  362.  
  363.     CLI
  364.     IN    AL,40H
  365.     MOV    AH,AL
  366.     STI
  367.     IN    AL,40H
  368.  
  369. ;The effect is to read the 1.19318MHz system clock.  This 16-bit value is
  370. ;incremented (you guessed) 1193180 times a second, which makes it pretty random.
  371. ; It wraps around from 65536 to 0.  That bit of code, by the way, gives you the
  372. ;low order of the system clock in AH, and the high order in AL.  This byte
  373. ;reversal makes the numeric value even more random (and saves two bytes of code
  374. ;:).
  375. ;
  376. ;Oh, and in case you were wondering, the reason for the STI being the
  377. ;second-last instruction rather than the last, is that after an STI interrupts
  378. ;aren't disabled till the end of the next instruction (a defined and documented
  379. ;feature of the chip).
  380. ;
  381. ;Cheers,
  382. ;Mic
  383. ;-!- FMail 0.92
  384. ; ! Origin:  The Gate - Melbourne, Australia - +61-3-879-9082  (3:633/159)
  385.  
  386. ;[And back to the Ciriello code again]
  387.  
  388. ;SRAND - Seeds the random number generator with the value in AX.  If AX is null
  389. ;    the low order word of the number of clock ticks since midnight is used
  390.  
  391.     or    ax,ax        ;0?                v1.1
  392.     jnz    Srand1
  393.      int    1AH
  394.      mov    ax,dx
  395. Srand1:    mov    w1,0        ;v1.1
  396.     mov    w2,ax
  397.     ret
  398. Srand    ENDP
  399.  
  400.  
  401. CSEG    ENDS
  402.     END    Shuffle
  403.