[TulaAnti&ViralClub] PRESENTS ...
MooN_BuG, Issue 5, May 1998                                           file 016

                         ƒ¥­¥à â®àë á«ãç ©­ëå ç¨á«¥«
                                                        by All

     ‘ ¬®¥  ¯à®áâ®¥  -  áç¨â âì â¥ªãé¥¥ §­ ç¥­¨¥ ç á®¢, ­ ¯à¨¬¥à ¯® ¯à¥àë¢ ­¨î
Int   21h,  ­®  ¨­®£¤   ¡ë¢ ¥â  ­ã¦­®  ¯®«ãç¨âì  á«ãç ©­®¥  ç¨á«®  ¡¥§  ¢ë§®¢ 
¯à¥àë¢ ­¨ï. ‚®â ª ª ®¡ëç­® ¯à®£à ¬¬¨áâë à¥è îâ íâã ¯à®¡«¥¬ã
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
     Ž¤­®  á«ãç ©­®¥  ç¨á«®  ¨«¨  ­¥áª®«ìª®,  ­® ç¥p¥§ ­¥p ¢­®¬¥p­ë¥ ¨ ¡®«ìè¨¥
¯p®¬¥¦ãâª¨ ¢p¥¬¥­¨, â® ¬®¦­® ¨á¯®«ì§®¢ âì á«¥¤ãîé¨© ª®¤:

                PUSH   DS
                SUB    DX,DX
                MOV    DS,DX
                MOV    AX,DS:[46Ch]
                MOV    BX,SOME_VALUE+1
                DIV    BX
                POP    DS

     ‚  DX  ¡ã¤¥â  á ¬®¥  ­ áâ®ïé¥¥  á«ãç ©­®¥-¯p¥á«ãç ©­®¥  ç¨á«®  ®â ­ã«ï ¤®
SOME_VALUE  ¢ª«îç¨â¥«ì­®!  â®  ¤«ï  ¨£p  â¨¯   "Œ®páª®© ®©", ¢®¯p®á-®â¢¥â á®
á«ãç ©­ë¬  ¢p¥¬¥­¥¬ ­  p §¤ã¬ìï. Œ®¦­® ¯® ¢ªãáã ¤®¡ ¢¨âì XOR, ADD ¨ ROL/ROR ¤®
¤¥«¥­¨ï.
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
‚ë¤à ­­® ¨§ BPC/C++, à¥§ã«ìâ â ¯®¬¥é ¥âáï ¢ DX

                MOV     CX,wValueHi
                MOV     BX,wValueLo
                MOV     ax,015Ah                ; Magic values
                MOV     si,4E35h

                MUL     BX
                JCXZ    L1
                XCHG    AX,CX
                MUL     SI
                ADD     AX,CX
L1:             XCHG    AX,SI
                MUL     BX
                ADD     DX,SI

                ADD     AX,1
                ADC     DX,0
                MOV     wValueHi,DX
                MOV     wValueLo,AX
                xchg    AX,dx
                AND     AX,7FFFh                ; (C) Bugland :-)
                cwd
                mov     bx,SOME_VALUE+1
                div     bx
                ...
wValueLo        dw      ?
wValueHi        dw      ?
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
‡­ ç¥­¨ï ¢ à¥£¨áâà å si ¨ di ¬®¦­® ¨á¯®«ì§®¢ âì ª ª á«ãç ©­ë¥

                xor si,di
                inc si
                rol si,1
                xchg si,di

Œo¦­o ¯poáâo ¯o¯po¡o¢ âì:

.model tiny
.code
.data
.286
.startup

        mov ax,13h
        int 10h

        push 0a000h
        pop es
out:
        xor si,di
        inc si
        rol si,1
        xchg si,di

        mov al,cl
        stosb
        loop out
        mov ah,1
        int 16h
        jz out
        int 20h

        end
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
public domain, linear congruential pseudo-random
number generator routine by Jerry Coffin.

These do have a bit of a defect - there's one bit that actually
is predictable - the two rotates at the end of rand bury it in
the middle of the number instead of the end where it causes
numbers to alternate between odd and even.  As is, in binary you
can still see the alternation, but when converted to decimal, it
generally isn't too obvious.  An alternative is to use a 32 bit
generator and only use 16 bits of what it produces.  With 16 bit
registers, this is quite a bit more work, and for light duty use,
this one seems to be adequate. For serious statistical analysis,
you should probably investigate other algorithms.

srand should be called before rand is used, but needs only to be
called once at the beginning of the program.  It uses the seconds
and hundredths of a second read from DOS to seed the generator
which is relatively random due to the imprecision of the clock,
but as noted above, it's likely not particularly good for serious
statistical analysis but seems to work fine for games and such.

Assemble with a definition to tell it what memory model to use, as in:

tasm /Dmemmodel=small /mx rand

As is, these will assemble to produce names that a c compiler
will recognize (lower case with an underscore before the
function name.) If you wish to call from BASIC, Pascal, etc.
change the language on the model line to suit...

|

%.model memmodel,c

.data
k1      dw      9821
k2      dw      1
;
; These two values are relatively critical to the quality of
; number generated.  They were picked in accordance with Knuth
; Vol. 2, which you should likely read youself if you want to
; modify this or produce another of your own...
;
seed    dw      ?

.code

        public rand
rand proc
;
; returns a 16 bit semi-poor quality pseudo-random number in AX.
;
; destroys AX and DX.
;
        mov     ax,seed
        imul    k1
        add     ax,k2
        mov     seed,ax
        ror     al,1
        rol     ah,1
        ret
rand endp

        public srand
srand proc
;
; Seeds rand from the DOS clock.
;
        mov     ah,2ch
        int     21h
        mov     seed,dx
        ret
srand   endp
        end
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
  rnd_c dw ?

; ˆ­¨æ¨ «¨§ æ¨ï:
r_init proc
   mov ax,40h
   mov es,ax
   mov ax,es:6ch
   mov rnd_c,ax
   ret
r_init endp

; ‘ ¬  ¯à®æ¥¤ãà 
random proc
   mov ax,rnd_c
   mov dx,23917
   mul dx
   add ax,997
   mov rnd_c,ax
   ret
random endp  ; ax=rnd
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
random  proc near
;
;  Returns:
;   AX = Random number between 0 and AX-1
;
  push bx cx dx
  mov bx,ax
  call random_
  mov cx,dx
  mul bx
  mov ax,cx
  mov cx,dx
  mul bx
  add ax,cx
  adc dx,0
  mov ax,dx
  pop dx cx bx
  ret
random  endp

random_  proc near
;
;  Updates randseed and returns its value in AX:DX
;
  push bx cx si
  mov si,8405h
  mov ax,word ptr cs:randseed
  mov bx,word ptr cs:randseed[2]
  mov cx,ax
  mul si
  shl cx,3
  add ch,cl
  add dx,cx
  add dx,bx
  shl bx,2
  add dx,bx
  add dh,bl
  shl bx,5
  add dh,bl
  add ax,1
  adc dx,0
  mov word ptr cs:randseed,ax
  mov word ptr cs:randseed[2],dx
  pop si cx bx
  ret
random_  endp

randomize proc near
;
;  Initializes randseed with timer value
;
  push ax cx dx
  mov ah,2Ch
  int 21h
  mov word ptr cs:randseed,cx
  mov word ptr cs:randseed[2],dx
  pop dx cx ax
  ret
randomize endp

randseed dd ?
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
RTL ®â á¥¤ì¬®£® ¯ áª «ï:

const
     RandIntSd  :longint=$12345678;    { ­ ç «ì­®¥ §­ ç¥­¨¥ }
     RandFactor :word   =$8405;        { 8405h }

Procedure  NextRand; near; assembler;
 asm
    MOV AX,word ptr RandIntSd
    MOV BX,word ptr RandIntSd+2
    MOV CX,AX
    MUL BX
    MUL RandFactor
    SHL CX,3
    ADD CH,CL
    ADD DX,CX
    ADD DX,BX
    SHL BX,2
    ADD DX,BX
    ADD DH,BL
    SHL BX,5
    ADD DH,BL
    ADD AX,1
    ADC DX,0
    MOV word ptr RandIntSd,AX
    MOV word ptr RandIntSd+2,DX
{    RETN}
 end;


Function  Rand16 :word; assembler;
 asm  CALL NextRand  end;


Function  Rand32 :longint; assembler;
 asm  CALL NextRand  end;
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Rnd:    mov ax,word ptr cs:[r2]         ;(‡¤¥áì ­¥¡o«ìè ï o¯â¨¬¨§ æ¨ï ªo¤  ;)
        mov byte ptr cs:[r1],al         ;
        add ah,al
        mov al,byte ptr cs:[r3]
        mov byte ptr cs:[r2],al
        add al,ah
        rol al,1
        mov byte ptr cs:[r3],al
        ret                             ;H  ¢ëåo¤¥: AL (0..255)

r3:     db 33           ;\
r2:     db 98           ;-- ‡¤¥áì ¬o£yâ ¡ëâì «î¡ë¥ ç¨á« .
r1:     db 3            ;/  (íâo ­ ç «ì­ ï yáâ ­o¢ª  RND-£¥­¥p âop )
           ;(r3,r2,r1 ­¥o¡åo¤¨¬o p ááâ ¢¨âì _âo«ìªo_ ¢ â ªo© oç¥p¥¤­oáâ¨)

p¨ ª ¦¤o¬ ¢ë§o¢¥, Rnd ¡y¤¥â ¢ë¤ ¢ âì ¢ AL á«yç ©­o¥ ç¨á«o.
—âo¡ë ¯o«yç¨âì ç¨á«o ¢ § ¤ ­­ëå ¯p¥¤¥« å:

Lab1:   call Rnd
        mov dh,al
        call Rnd
        mov dl,al
        cmp dx,100      ;­¨¦­¨© ¯p¥¤¥« (100)
        jc  Lab1
        cmp dx,65001    ;¢¥på­¨© ¯p¥¤¥« + 1
        jnc Lab1
        mov ax,dx       ;H  ¢ëåo¤¥: AX (100..65000)
        ret
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Random  Proc
        Mov  AL,00000000b
        Out  43h,AL
        In   AL,40h
        Mov  AH,AL
        In   AL,40h
        XChg AL,AH
        Ret
Random  Endp
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
rndword:
 ;-> ax - rnd 0..65535
    PUSH        DX
    MOV AX,[cs:rnd_var_1]
    MOV     DX,AX
    MOV     AX,[cs:rnd_var_2]
    MOV     [cs:rnd_var_1],AX
    ADD     AX,DX
    MOV     DX,AX
    MOV     AX,[cs:rnd_var_3]
    MOV     [cs:rnd_var_2],AX
    ADD     AX,DX
    ROR     AX,1
    MOV     [cs:rnd_var_3],AX
    POP     DX
    RET

rnd_var_1       dw 64h  ;   DB      64
rnd_var_2       dw 14h
rnd_var_3       dw 29h+0b8h*256

randomize:
 push es
 PUSH    AX
 XOR     AX,AX
 MOV     ES,AX
 MOV     AX,[es:046Ch]
 MOV     [cs:rnd_var_1],AX
 MOV     AX,[es:0468h]
 MOV     [cs:rnd_var_2],AX
 MOV     AX,[es:0467h]
 MOV     [cs:rnd_var_3],AX
 POP     AX
 POP     ES
 RET

rndword2:
  ;cx - max rnd
  ;-> ax - rnd
 or cx,cx
 jnz rndword2l_1
 xor ax,ax
 ret
rndword2l_1:
 PUSH    CX
 PUSH    DX
 MOV     AX,-1 ;FFFF
 XOR     DX,DX
 DIV     CX
 PUSH    AX
 CALL   rndword
 POP     CX
 XOR     DX,DX
 DIV     CX
 POP     DX
 POP     CX
 cmp ax,cx
 jc rndword2l1 ;nz rndword2l1
 ;dec ax
 mov ax,cx
 dec ax
rndword2l1:
 RET
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
