001 ;**************************************************
002 ; 以下代码由“老罗代码着色器”0.2版进行着色
003 ; 测试文件名:Random.asm
004 ; 测试日期: 2002-12-29
005 ;**************************************************
006
007 ;*********************************************************
008 ;程序名称:随机数的产生原理与实现
009 ;作者:罗聪
010 ;日期:2002-11-21
011 ;出处:http://www.LuoCong.com(老罗的缤纷天地)
012 ;注意事项:如欲转载,请保持本程序的完整,并注明:
013 ;转载自“老罗的缤纷天地”(http://www.LuoCong.com)
014 ;*********************************************************
015
016 .386
017 .model flat, stdcall
018 option casemap:none
019
020 include \masm32\include\windows.inc
021 include \masm32\include\kernel32.inc
022 include \masm32\include\user32.inc
023 includelib \masm32\lib\kernel32.lib
024 includelib \masm32\lib\user32.lib
025
026 WndProc proto :DWORD, :DWORD, :DWORD, :DWORD
027 iRand proto :DWORD, :DWORD
028
029 .const
030 IDC_BUTTON_GENERATE equ 3000
031 IDC_EDIT_FIRST equ 3001
032 IDC_EDIT_SECOND equ 3002
033
034 .data
035 szDlgName db "lc_dialog", 0
036 szCaption db "Rand Number Generator by LC", 0
037 szText db 255 dup(0)
038 szTemplate db "(%d ~ %d)随机数:", 13, 10, 13, 10,\
039 " %d", 13, 10, 13, 10,\
040 "老罗的缤纷天地", 13, 10,\
041 "http://www.LuoCong.com", 0
042 nFirst dd 0
043 nSecond dd 0
044
045 .code
046 main:
047 invoke GetModuleHandle, NULL
048 invoke DialogBoxParam, eax, offset szDlgName, 0, WndProc, 0
049 invoke ExitProcess, eax
050
051 WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
052 LOCAL hEdit: HWND
053
054 .if uMsg == WM_CLOSE
055 invoke EndDialog, hWnd, 0
056
057 .elseif uMsg == WM_COMMAND
058 mov eax, wParam
059 mov edx, eax
060 shr edx, 16
061 movzx eax, ax
062 .if edx == BN_CLICKED
063 .if eax == IDCANCEL
064 invoke EndDialog, hWnd, NULL
065 .elseif eax == IDC_BUTTON_GENERATE || eax == IDOK
066 ;获得上限:
067 invoke GetDlgItemInt, hWnd, IDC_EDIT_FIRST, NULL, TRUE
068 mov nFirst, eax
069 ;获得下限:
070 invoke GetDlgItemInt, hWnd, IDC_EDIT_SECOND, NULL, TRUE
071 mov nSecond, eax
072 ;产生随机数:
073 invoke iRand, nFirst, nSecond
074 ;输出:
075 invoke wsprintf, addr szText, addr szTemplate, nFirst, nSecond, eax
076 invoke MessageBox, hWnd, addr szText, addr szCaption, MB_OK or MB_ICONINFORMATION
077 .endif
078 .endif
079 .else
080 mov eax, FALSE
081 ret
082 .endif
083 mov eax, TRUE
084 ret
085 WndProc endp
086
087 ;**********************************************************************
088 ; 函数功能:产生范围从 first 到 second 的随机数
089 ; 传入参数:
090 ; first = 下限
091 ; second = 上限
092 ; 返回参数:
093 ; eax = Rand_Number
094 ; 所用公式:
095 ; Rand_Number = (Rand_Seed * X + Y) mod Z
096 ; 补充说明:
097 ; (1)本例中用 GetTickCount 来取得随机数种子,
098 ; 在实际应用中,可用别的方法代替。
099 ; (2)要产生随机数,X和Y其中之一必须是素数,
100 ; 所以 X = 23, Y = 7(可用别的素数代替)
101 ;**********************************************************************
102 iRand proc uses ecx edx first:DWORD, second:DWORD
103 invoke GetTickCount ; 取得随机数种子,当然,可用别的方法代替
104 mov ecx, 23 ; X = ecx = 23
105 mul ecx ; eax = eax * X
106 add eax, 7 ; eax = eax + Y (Y = 7)
107 mov ecx, second ; ecx = 上限
108 sub ecx, first ; ecx = 上限 - 下限
109 inc ecx ; Z = ecx + 1 (得到了范围)
110 xor edx, edx ; edx = 0
111 div ecx ; eax = eax mod Z (余数在edx里面)
112 add edx, first ; 修正产生的随机数的范围
113 mov eax, edx ; eax = Rand_Number
114 ret
115 iRand endp
116
117 end main
118 ;******************** over ********************
119 ;by LC