产生随机数_汇编
1、keil中的rand函数反编译结果:
/* TEST.c */
#include
void main(void)
{
CHAR i, j, k;
i = 0x5f;
j = rand();
k = 0xf5;
}
反编译结果,随机数放在R7中
;==========================================================================
Q0003: MOV R4,08H ;0003 AC 08
MOV R5,09H ;0005 AD 09
MOV R6,0AH ;0007 AE 0A
MOV R7,0BH ;0009 AF 0B
MOV R0,#0FH ;000B 78 0F Q000D: MOV A,R7 ;000D EF
MOV C,ACC.2 ;000E A2 E2
MOV A,R4 ;0010 EC
JB ACC.6,Q0015 ;0011 20 E6 01
CPL C ;0014 B3 Q0015: ANL A,R5 ;0015 5D
ANL A,R6 ;0016 5E
ANL A,R7 ;0017 5F
CPL A ;0018 F4
JNZ Q001F ;0019 70 04
MOV R4,A ;001B FC
MOV R5,A ;001C FD
MOV R6,A ;001D FE
MOV R7,A ;001E FF Q001F: MOV A,R7 ;001F EF
RRC A ;0020 13
MOV R7,A ;0021 FF
MOV A,R6 ;0022 EE
RRC A &nb
2、一个简单的随机数发生函数:
rand8reg是得到的随机数,为了更随机,可以把它与定时器相加
如果可以把rand8reg保存在非易失性存储器中更好,但是什么时候保存需要认真考虑
;==============================================================
; NAME: rand8
; DESCRIPTION: get a 8bit random NUMBER
; Function: This routine sends calc a 8bit random NUMBER
; Attention: get a random "rand8reg" before initialize the program
; Calls: None
; Input: rand8reg
; Outputs: rand8reg
; Register Usage: A, psw
;--------------------------------------------------------------
rand8:
mov a, rand8reg
jnz rand8b
cpl a
mov rand8reg, a
rand8b:
anl a, #10111000b
mov c, p
mov a, rand8reg
rlc a
mov rand8reg, a
ret
3、这个可能复杂一些:
其实和周航慈《单片机程序设计基础》上的例子是一样的,使用线性移位寄存器构成随机数发生器
;**********************************************************;
;* Random *;
;*Random_Buf 6个字节看成48个位,可以表示280亿个数值,原理:用反*;
;*馈函数F()把这280亿个无顺序的放在一个可以旋转数码盘上,程序 *;
;*有定时器在跑,当随机发生时,让转盘转计数器的值圈数即可得到一个*;
;*随机数. *; ;*奇校验反馈函数d0=d48+d7+d5+d4+d2+d1+1,6Byte有280亿种状态 *;
;**********************************************************;
Random:
PUSH ACC
MOV RandomREG,Count
Data_Rotate:
MOV A,Random_Buf+5 ;取D41-D48的当前状态
RLC A ;将D48提取到标志中去
MOV A,Random_Buf ;取D1-D8的当前状态
ANL A,#5BH ;提取D7,D5,D4,D2,D1的当前值
MOV ACC.7,C ;再加上D48的当前值
MOV C,PSW.0 ;取得偶校验的结果
CPL C ;转换成奇校验,且得到反馈函数的值
MOV A,Random_Buf ;开始移位操作,先处理低字节
RLC A ;将反馈函数的值移入,最高位移出
MOV Random_Buf,A ;保存移位后的结果
MOV A,Random_Buf+1 ;再依次进行其他字节的移位操作
RLC A
MOV Random_Buf+1,A
MOV A,Random_Buf+2
RLC A
MOV Random_Buf+2,A
MOV A,Random_Buf+3
RLC A
MOV Random_Buf+3,A
MOV A,Random_Buf+4
RLC A
MOV Random_Buf+4,A
MOV A,Random_Buf+5
RLC A
MOV Random_Buf+5,A ;完成巨型数字转盘转动一格
DJNZ RandomREG,Data_Rotate ;取当前时间随机时间转动n格 Random_Exit:
POP ACC
RET
4、最终使用的程序
使用一个简单的随机数发生器产生种子
运行中用TL0作为干扰
; TEST.asm
; TEST
;--------------------------------------------------------------
;==============================================================
; Define
;--------------------------------------------------------------
STACK_TOP EQU 0D0H ; STACK : 48Bytes
Random_Buf EQU 70H ; VARIABLE BUFFER (70H~75H)
RND0 EQU 70H ; VARIABLE 第1字节
RND1 EQU 71H ; VARIABLE 第2字节
RND2 EQU 72H ; VARIABLE 第3字节
RND3 EQU 73H ; VARIABLE 第4字节
RND4 EQU 74H ; VARIABLE 第5字节
RND5 EQU 75H ; VARIABLE 第6字节
RandCount EQU 76H ; VAIRABLE 跳动格数
rand8reg EQU 77H ; VAIRABLE 简单随机数,用来产生种子和跳动格数
;==============================================================
; MAIN PROGRAM : 程序入口
;==============================================================
ORG 0000H ; ; main program
LJMP main ;
ORG 0003H ; ; Int0 Interrupt
RETI ;
ORG 000BH ; ; T0 Interrupt
RETI ;
ORG 0013H ; ; Int1 Interrupt
RETI ;
ORG 001BH ; ; T1 Interrupt
RETI ;
ORG 0023H ; ; Si1 Interrupt
RETI ;
ORG 002BH ; ; T2 Interrupt
RETI ;
ORG 0033H ; ;
RETI ;
ORG 003BH ; ; Si2 Interrupt
RETI ;
ORG 0043H ; ; Int2 Interrupt
RETI ;
ORG 004BH ; ; Int3 Interrupt
RETI ;
ORG 0053H ; ; Int4 Interrupt
RETI ;
ORG 005BH ; ; Int5 Interrupt
RETI ;
ORG 0063H ; ; WatchDog Interrupt
RETI ;
ORG 0100H
; 程序入口
main:
CLR EA
; Reset RAM
MOV R0, #0FFH
ResetRam:
MOV @R0, #00H
DJNZ R0, ResetRam
MOV SP, #STACK_TOP
LCALL Init_Random ; 初始化随机数发生器
MOV R0, #20H
MOV R1, #40H
RANDLOOP:
LCALL Random ; 产生随机数
MOV A, RND0
MOV @R0, A ; 把随机数暂存到RAM中
INC R0
DJNZ R1, RANDLOOP ; 循环取40H个随机数
NOP
NOP
LJMP main
;==============================================================
; NAME: Init_Random
; DESCRIPTION: initialize the random ; Function: give the VALUE of Random_Buf and RandCount
; Calls: None
; Input: Random_Buf, RandCount ; Outputs: Random_Buf
; Register Usage: A, psw ;--------------------------------------------------------------
Init_Random:
ADD A, B
ADD A, R0
ADD A, R1
&nbs
5-----------------------------------------------------
DATA SEGMENT
CC DB '+'
ww db '-'
GG DB '='
II DB 0DH,0AH,'$'
AA DB 5 DUP(?)
www dw 0
ghh db '0',0dh,0ah,'$'
bnm dw 0
DATA ENDS
STACK SEGMENT
DB 200 DUP(0) STACK ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA,SS:STACK
START: MOV AX,DATA
MOV DS,AX
MOV CX,20
CALL RAND ;产生一随机数
CALL MCAT ;将随机数转换为16进制表示的ASCII码字符
MOV AX,BX
PUSH AX
CMP www,0 ;WWW=0?
JE A1 ;执行'+'
CMP www,1 ;www=1?
JE A2 ;执行'-'
A1: MOV DL,CC ;显示'+'
MOV AH,2
INT 21H
CALL RAND ;产生另一随机数
add bx,0fh
CALL MCAT ;将随机数转换为16进制表示的ASCII码字符
MOV DL,GG ;显示'='
MOV AH,2
INT 21H
POP AX
ADD AX,BX
cmp ax,0
jne yjw1
lea dx,ghh
mov ah,9
int 21h
jmp qq1
yjw1: JMP B1
A2: MOV DL,WW ;显示'-'
MOV AH,2
INT 21H
mov cx,65535 mai1: loop mai1
CALL RAND1
CALL MCAT
MOV DL,GG
MOV AH,2
INT 21H
POP AX
Sbb AX,BX
cmp ax,0
jne yjw2
lea dx,ghh
mov ah,9
int 21h
jmp qq1 yjw2: JMP B1
B1: MOV BX,AX
CALL MCAT
lea DX,II
MOV AH,9
INT 21H QQ1: MOV AH,4CH
INT 21H MCAT PROC ;将随机数转换为16进制表示的ASCII码字符子程序
PUSH AX
push bx
PUSH CX
PUSH DX
CMP BX,9
JA S1
PUSH AX
PUSH BX
PUSH CX
PUSH DX
mov ax,bx
mov bl,5
div bl
cmp ah,3
jae vb1
mov www,1
jmp vn1 vb1:mov www,0 vn1:pop dx
pop cx
pop bx
pop ax
ADD BL,30H
MOV AA,BL
MOV AA+1,'$'
LEA DX,AA
MOV AH,9
INT 21H
JMP s3 s1:MOV CL,4
MOV AL,0
PUSH BX
SHL BX,CL
CMP BH,9
JBE V1
SUB BH,9
ADD BH,40H
JMP MM1 V1:ADD BH,30H MM1:MOV AA,BH
POP BX
AND BL,0FH
PUSH AX
PUSH BX
PUSH CX
PUSH DX
mov ax,bx
mov bl,5
div bl
cmp ah,3
jae vb2
mov www,1
jmp vn2 vb2:mov www,0 vn2:pop dx
pop cx
pop bx
pop ax
CMP BL,9
JBE TT1
SUB BL,9
ADD BL,40H
JMP RR1 TT1: ADD BL,30H RR1: MOV AA+1,BL
MOV AA+2,'$'
LEA DX,AA
MOV AH,9
INT 21H s3:POP DX
POP CX
POP BX
POP AX
RET
MCAT ENDP
RAND PROC
PUSH CX
PUSH DX
PUSH AX
STI
MOV AH,0 ;读时钟计数器值
INT 1AH
MOV AX,DX ;清高6位
AND AH,3
MOV DL,101 ;除101,产生0~100余数
DIV DL
MOV BL,AH ;余数存BX,作随机数
POP AX
POP DX
POP CX
RET
RAND ENDP
RAND1 PROC
PUSH CX
PUSH DX
PUSH AX
STI
MOV AH,0
INT 1AH
MOV ax,cx
AND AH,3
MOV DL,101
DIV DL
MOV BL,AH
POP AX
POP DX
POP CX
RET
RAND1 ENDP
CODE ENDS
END START
6----------------------------------------------
DATA SEGMENT RND DW 256 DUP(?) DATA ENDS
STAK SEGMENT STACK
DW 256 DUP(?) STAK ENDS
CODE SEGMENT
ASSUME DS: DATA, SS: STAK, CS: CODE
START: MOV AX, DATA
MOV DS, AX
LEA DI, RND
MOV BX, 256 LOP: CMP BX, 0
JZ EXIT
MOV AH, 2CH
INT 21H
MOV AL, DL
ADD AX, 159
MUL DL
XOR AH, 12
MOV [DI], AX
INC DI
INC DI
DEC BX
MOV CX, 0
LOP1: INC AX
PUSH CX
MOV CX, 250 LOP2: INC AX
LOOP LOP2
POP CX
LOOP LOP1
JMP LOP
EXIT: INT 3
MOV AH, 4CH
INT 21H
CODE ENDS
END START
断,在Debug下可以查看结果。。。。 在EXIT那里我设置了调试中
前面那个算法没效率。。。。。这个应该比较好了,虽然这个算法也没有经过什么严格的数
学
证明
住所证明下载场所使用证明下载诊断证明下载住所证明下载爱问住所证明下载爱问
,应该不符合正态分布,,这里只是提供一种思想吧。。。。 对了,CX里放的是需要产生随机数的个数。
DATA SEGMENT
PMPT1 DB 'Please input the decimal number for converting (format: xxxxx): $'
PMPT2 DB 0AH, 0DH, 'The binay result is : $'
RESLT DB 16 DUP ('0') BUF DW ?
COUNT DB 4
DATA ENDS
STA SEGMENT STACK S DW 30 DUP (0)
STA ENDS
CODE SEGMENT
ASSUME DS: DATA, SS: STA, CS: CODE
START: MOV AX, DATA
MOV DS, AX
MOV SI, -1
MOV CX, 0
LEA DX, PMPT1
MOV AH, 9
INT 21H
MOV BUF, 1000
MOV AH, 1
INT 21H
SUB AL, 30H
MOV AH, 0
MOV BX, 10000
MUL BX
MOV CX, AX
MOV DI, 10
INPLP: MOV AH, 1
INT 21H
SUB AL, 30H
MOV AH, 0
MOV BX, BUF
MUL BX
ADD CX, AX
MOV AX, BX
DIV DI
MOV BUF, AX
DEC COUNT
JNZ INPLP
MOV BX, CX
LEA DX, PMPT2
MOV AH, 9
INT 21H
NEXT: INC SI
AND BX, BX
JZ PR_RM_0
SHL BX, 1
JNC PR_0
MOV RESLT[SI], '1'
MOV DL, RESLT[SI]
MOV AH, 2
INT 21H
JMP NEXT PR_0: MOV DL, RESLT[SI]
MOV AH, 2
INT 21H
JMP NEXT PR_RM_0:MOV DL, RESLT[SI]
MOV AH, 2
INT 21H
INC SI
CMP SI, 16
JA EXIT
JMP PR_RM_0 EXIT: MOV AH, 4CH
INT 21H CODE ENDS
END START
7------------------------------------------------
Random:
push eax
db 0Fh, 031h ;EAX=随机数
xor edx, edx
div dword ptr [esp+8];EAX/种子
pop eax
ret 4
8------------------------------------------------
Random PROC Seed: DWORD ;返回值在eax
中。
mov eax , 12345678h
_GetTickCount = dword ptr $-4
call eax
xor edx , edx
div Seed
xchg edx , eax ;需要的是余数,在edx中。
ret 4
Random ENDP
9--------------------------------------------------------------------------
Random32 PROC
.data
seed DWORD 1
.code
push edx
mov eax, 343FDh
imul seed
add eax, 269EC3h
mov seed, eax ; save the seed for the next call
ror eax,8 ; rotate out the lowest digit (10/22/00)
pop edx
ret
Random32 ENDP
;--------------------------------------------------------
Randomize PROC
pushad
INVOKE GetSystemTime,OFFSET sysTime
movzx eax,sysTime.wMilliseconds
mov seed,eax
popad
ret
Randomize ENDP