Trao đổi với tôi

http://www.buidao.com

12/16/16

[MASM] Random numbers

Random numbers
Cách dùng hàm Random trong masm32.lib
Author: Benina

A-Lý thuyết:

Trước tiên ta khai báo:

include \masm32\m32lib\masm32.inc
includelib \masm32\m32lib\masm32.lib

Sau đó ta có thể dùng 2 hàm nrandom và nseed trong masm32.lib


-Hàm nseed (seed=tạo hạt) kết hợp với hàm GetTickCount để kích “bộ ngẫu nhiên” random
-Sau đó dùng hàm nrandom để tạo ra 1 số ngẫu nhiên trong khỏang từ 0--- >some_value theo code sau:


invoke GetTickCount
invoke nseed, eax
invoke nrandom, some_value ; gets pseudo-random number up to some_value.


Tra API reference ta có:

Hàm: GetTickCount

Hàm GetTickCount function tìm lại số mili giây đã trôi qua từ khi Windows khởi động.

DWORD GetTickCount(VOID)

Tham số hàm:

Hàm này ko có tham số.  

Giá trị trả về :

Nếu hàm này gọi thành công , giá trị trả về là một số mili giây trôi qua từ khi Windows khởi động.

Remarks (nhận xét):

Thời gian trôi qua được chứa trong một giá trị DWORD. Dù vậy, thời gian sẽ quay lại zero khi Windows đã chạy liên tục trong 49.7 days.
Windows NT: Nhận được thời gian trôi qua từ khi Windows khởi động  bằng cách tìm trong  System Up Time counter trong phần dữ liệu đã thực hiện (performance data) trong  registry key HKEY_PERFORMANCE_DATA. Giá trị trả về là một giá trị 8 byte.


Tra trong Help masm32.lib ta có:

Hàm: nrandom

nrandom proc base:DWORD

Mô tả:
Một thụat tóan Park Miller random algorithm được viết bởi Jaymeson Trudgen (NaN) và được optimised bởi Rickey Bowers Jr. (bitRAKE).

Tham số
1.  base  xác định vùng giới hạn của số random xuất ra từ Zero đến base.

Giá trị trả về:

Số Random với giới hạn từ zero đến  "base" chứa trong EAX.

Chú thích:

Seed (gieo hạt giống) cho thuật tóan random algorithm là set một biến GLOBAL trong một thủ tục được tách ra đính kèm trong library module. Biến này là nrandom_seed và biến này sẽ được set với một số có kích thước DWORD trước khi sử dụng thuật tóan này.

B-Ví dụ:

.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib
include \masm32\include\user32.inc
includelib \masm32\lib\user32.lib
include \masm32\m32lib\masm32.inc
includelib \masm32\m32lib\masm32.lib

.data
MsgBoxCaption  db "Iczelion Tutorial No.00",0
sFormat db '%4i',0
buffer dd 128 dup (0)

.code
start:

invoke GetTickCount
invoke nseed,eax
invoke nrandom,500 ; eax return, < some_value=500

invoke wsprintf,addr buffer,offset sFormat, eax
invoke MessageBox, NULL, addr buffer, addr MsgBoxCaption, MB_OK
invoke ExitProcess, NULL

end start

C. Source trong file nrand.asm:

Đây là source của hai hàm nrand và nseed trong file nrand.asm:

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
;
;                     Park Miller random number algorithm.
;
;                      Written by Jaymeson Trudgen (NaN)
;                   Optimized by Rickey Bowers Jr. (bitRAKE)
;
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

      .486                      ; create 32 bit code
      .model flat, stdcall      ; 32 bit memory model
      option casemap :none      ; case sensitive

    .code

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

align 4

nrandom PROC base:DWORD

    mov eax, nrandom_seed

  ; ****************************************
    test eax, 80000000h
    jz  @F
    add eax, 7fffffffh
  @@:  
  ; ****************************************

    xor edx, edx
    mov ecx, 127773
    div ecx
    mov ecx, eax
    mov eax, 16807
    mul edx
    mov edx, ecx
    mov ecx, eax
    mov eax, 2836
    mul edx
    sub ecx, eax
    xor edx, edx
    mov eax, ecx
    mov nrandom_seed, ecx
    div base

    mov eax, edx
    ret

nrandom ENDP

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

nseed proc TheSeed:DWORD

    .data
      nrandom_seed dd 12345678
    .code

    mov eax, TheSeed
    mov nrandom_seed, eax

    ret

nseed endp

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

    end

C-Một số hàm random tham khảo thêm :

Hàm random một char trong một chuổi char cho trước được viết bởi  diablo2oo2:


+Tạo file include như sau:

RandomChar.inc :

;----------------------------------------------------------------------------
;written by diablo2oo2
;example:
;invoke RandomChar,chr$("ABCDEF0123456789") ; returns one of this char in eax
;----------------------------------------------------------------------------
RandomChar PROTO :DWORD
RAND32  PROTO :DWORD
InitRand32  PROTO

.data?
NaNRand dd ?

 .code
RandomChar proc _string:DWORD
LOCAL _retvalue:BYTE
pushad

mov esi,_string
;---get lenght of string---
xor ecx,ecx
.while byte ptr[esi+ecx]!=0
inc ecx
.endw
;---get random char---
invoke InitRand32
invoke RAND32,eax
movzx eax,ax
cdq
idiv ecx
mov al,byte ptr[esi+edx]
mov _retvalue,al
popad

movzx eax,_retvalue
ret
RandomChar endp

;----------------------------------------------------------------------------
;                 ----random number generator by NaN---
;           ---(modified a bit to make it a procedure by Exagone)---
;----------------------------------------------------------------------------
SWAP MACRO M1:REQ, M2:REQ
xor M1, M2
xor M2, M1
xor M1, M2
ENDM

InitRand32 proc
  db 0fh,31h
  shr eax, 2
  add eax, 1
  mov NaNRand, eax
  ret
InitRand32 endp 
 
RAND32 proc base:DWORD
  ; Random number generator based on the Real time clock
  ; and the Park, Miller random number algorithm
  ;
  ; Coded by NaN for WIN32ASM
  ; May 5, 2001
  ; rev 2.
  push ecx
  push edx


  mov eax, NaNRand   
  mov edx,0
  mov ecx, 127773 ;q
  div ecx      ; eax == floor( seed / q)
               ; edx == remainder
  SWAP eax, edx
  push edx
  mov ecx, 16807
  mul ecx      ; eax = mul of remainder * a
  pop edx      ; edx == floor of seed/q
 
  SWAP eax, edx
  push edx
  mov ecx, 2836
  mul ecx
  pop edx      ; edx == mull of rem * a
               ; eax == mull of seed/q * r
              
  sub edx, eax
  mov eax, edx   
  mov NaNRand, eax ; save next seed
  mov ecx, base
  mov edx, 0
  div ecx
  mov eax, edx
  pop edx
  pop ecx
 ret
RAND32 endp


+Cách sử dụng hàm RandomChar:

-Khai báo phần include :  include randomplus.inc
-Khai báo một mảng các ký tự trong .data mà ta cần random chỉ các ký tự đó thôi. Ví dụ:
sArrayRandom db "ABCDEF0123456789",0
-Trong code ta gọi hàm:
invoke RandomChar,offset sArrayRandom
-Kết quả là eax chứa mã hex của ký tự random


+Ví dụ:

.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib
include \masm32\include\user32.inc
includelib \masm32\lib\user32.lib

include randomChar.inc

.data

MsgBoxCaption  db "Iczelion Tutorial No.00",0
sFormat db '%4c',0
buffer dd 128 dup (0)
sArrayRandom db "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",0

.code
start:


invoke RandomChar,offset sArrayRandom

invoke wsprintf,addr buffer,offset sFormat, eax
invoke MessageBox, NULL, addr buffer, addr MsgBoxCaption, MB_OK
invoke ExitProcess, NULL

end start

;------------------------------------------------------------------------------ 
 Source code:  Win32 386+ Random-Number-In-Range Generator. (Team vx 29a)


; Win32 386+ Random-Number-In-Range Generator.
;
; Most Win32 random number generators I've come across so far were
; actually rather predictable, so here goes my attempt to code a
; truely random one. It's small, simple and reasonably fast.
;

                .386
                .MODEL  FLAT

EXTRN           GetTickCount:PROC
EXTRN           ExitProcess:PROC

                .DATA

Random_Seed     DD      0

                .CODE
START:
                CALL    GetTickCount            ; Initialize random seed.
                MOV     Random_Seed, EAX        ; This can be anything.

                MOV     EAX, 10                 ; Returns a random value
                CALL    Random_EAX              ; between 0 and 9.

                PUSH    0
                CALL    ExitProcess

;  Entry: EAX == Max_Val.
; Return: EAX == Random number between 0..Max_Val-1.
Random_EAX:
                PUSH    ECX                     ; Save registers that get
                PUSH    EDX                     ; changed.

                PUSH    EAX                     ; Save Max_Val.

                CALL    GetTickCount            ; Get random value.

                MOV     ECX, Random_Seed        ; Get random seed.

                ADD     EAX, ECX                ; Adjust random value with
                                                ; random seed.

                ROL     ECX, 1                  ; Adjust random seed.
                ADD     ECX, 666h

                MOV     Random_Seed, ECX

                ; Perform CRC-32 on semi-random number
                ; to obtain a truely random number.

                PUSH    32
                POP     ECX

CRC_Bit:        SHR     EAX, 1                  ; Bit is set?
                JNC     Loop_CRC_Bit

                XOR     EAX, 0EDB88320h

Loop_CRC_Bit:   LOOP    CRC_Bit                 ; Do all 32 bits.

                POP     ECX                     ; ECX = Max_Val.

                XOR     EDX, EDX                ; Divide truely random value
                DIV     ECX                     ; by Max_Val.

                XCHG    EDX, EAX                ; Remainder is the
                                                ; random-in-range number.

                OR      EAX, EAX                ; Test for zero.

                POP     EDX
                POP     ECX

                RETN

                END     START



HẾT TUT

Benina (10/11/2005)

Moded (26/9/2007)