2017-08-09 140 views
4

我試圖在程序集中創建一個完整的隨機數,但每次啓動程序時,它都會以相同的順序給出相同的數字。 如果數字是12,132,4133或其他東西,它會在我每次啓動代碼時重複它們。如何在程序集中生成隨機數生成器?

我試圖製作的程序就像猜謎遊戲。

IDEAL 
MODEL small 
STACK 100h 
DATASEG 
;vars here 
RNG_Seed dw ? 

CODESEG 
; Generates a pseudo-random 15-bit number. 
; Parameters: <none> 
; Clobbers: AX, DX 
; Returns: AX contains the random number 
proc GenerateRandNum 
    push bx 
    push cx 
    push si 
    push di 


    ; 32-bit multiplication in 16-bit mode (DX:AX * CX:BX == SI:DI) 
    mov ax, [RNG_Seed] 
    xor dx, dx 
    mov cx, 041C6h 
    mov bx, 04E6Dh 
    xor di, di 
    push ax 
    mul bx 
    mov si, dx 
    xchg di, ax 
    mul bx 
    add si, ax 
    pop ax 
    mul cx 
    add si, ax 


    ; Do addition 
    add di, 3039h 
    adc si, 0 


    ; Save seed 
    mov [RNG_Seed], di 


    ; Get result and mask bits 
    mov ax, si 
    and ah, 07Fh 


    pop di 
    pop si 
    pop cx 
    pop bx 
    ret 
endp GenerateRandNum 

我該怎麼做才能在每次運行中得到不同的隨機數?

+0

您的程序是否在沒有操作系統的情況下運行? – James

+0

@詹姆斯你在OS中意味着什麼? –

+0

操作系統 – Ped7g

回答

4

您需要用「random」來初始化RNG_Seed。這在計算機等確定性機器上實際上有點問題。

特別是如果你希望隨機對於加密足夠強大,那麼研究當前的解決方案需要幾個小時,甚至包括一些工業解決方案,甚至包含帶有白噪聲發生器的特殊硬件芯片,用作隨機值生成器。

正如你只想要一款遊戲一樣,它並沒有那麼糟糕,但仍然有點棘手。

我猜你是在實模式下(如使用16B寄存器),所以讀取BIOS蜱,因爲午夜熵的一個來源:

xor ah,ah ; ah = 0 
int 1Ah ; returns in cx:dx ticks since midnight (18.2Hz ticks) 
; let's mix the cx:dx a bit together to get a bit more entropy out of it 
rol cx,8 
xor dx,cx 
xor [RNG_Seed],dx ; "add" that entropy to the original seed 

這將提高它一下,但它的仍然有點差解決方案(同時運行遊戲可能容易產生相同的隨機值),所以這裏是另一個關於「便宜」熵源的建議:

請求播放器輸入名稱(至少3字符)和每次擊鍵的時間通過在等待密鑰的同時一直做inc counter,每次保持計數器的低4位(3個字符+輸入= 4 * 4位=總共16位)。然後再次「添加」(xor)到RNG_Seed

這兩件事情應該爲遊戲RNG產生足夠的熵(但對於安全目的來說還不夠,如加密)。


編輯:在評論中指出,混合不同的種子值時,確保他們要麼不涉及,或使用而不是addxor。我最初的想法是從午夜開始使用BIOS刻度,xor - 針對變量的一些隨機內存(可能爲零,BTW,在exe加載期間由OS清除),然後測量用戶的擊鍵時間,那些組成爲4:4 :4個4位按鍵(無xor,相互連接,直到滿16b準備好),並在主種子上使用xor的最終值。由於擊鍵與BIOS嘀嗒聲沒有任何關係,因此這不應該干擾,並且在這種情況下應該可以很好地工作。

此外,爲什麼4:4:4:4從擊鍵,而不是單次16b值每次反覆異或。我希望你可以通過調用int 16h, ah=1來實現這個按鍵延遲計數器,所以如果你無限循環這個並且增加一些計數器,它很可能會非常快速地運行超過16個值(我估計在千分之一秒內)。然後使用這種計數器的低4位很難與用戶如何快速按鍵相關。雖然在非常慢的計算機上使用等待用戶的完整16b實際上可能會產生高位中的某些相似的位模式(即,用戶每次在10000-13000的計數器值之間的某個位置打擊鍵 - >最高2位始終爲零並且整個頂部8每次比特將非常相似)。所以這就是我的意思,通過使用低4位,將它們中的四個連接在一起形成16b值。如果用戶輸入更長的名稱,我甚至不會使用這些進一步的按鍵進行種子調整,只有前四個。我可能會做一些調試,看看它在現實中是如何工作的,也許我對結果過於樂觀,並且存在一些隱藏的同步式捕獲。但我懶得寫它並嘗試(這就像20行代碼,但需要dosbox和一些DOS調試器)。

+4

從(主要)確定性機器創建熵總是我最喜歡的任務之一 - 非常有創意!編寫一個大的熵源列表以及它們的大小可能很有趣(這可能很難證明)。例如,在'rdtsc','rdseed'和'rdrand'旁邊,到下一個垂直回掃的時間(以任何單位)是一個很好的來源:) –

+1

@ S.josh:['RDRAND r16'](https:/ /hjlebbink.github.io/x86doc/html/RDRAND.html)*應該*工作在16位模式下,因爲它不使用VEX編碼(這就是爲什麼一些BMI/BMI2指令不可用於16位模式)。但是,當然只在支持它的CPU上,即使如此,特定CPU中的RNG硬件也可能出現故障,導致其返回CF = 0的非隨機數據。 –

+2

@ Ped7g:對於可能相關的事物,'xor'是一個危險的混合函數。 [正如@Yakk說](https://stackoverflow.com/questions/45069219/how-to-succinctly-portably-and-thoroughly-seed-the-mt19937-prng#comment77114547_45070076):'+'通常更好:'' x + x'只燒錄'x'中的1位熵,而'x^x'將它們全部燒燬,在兩次使用相同值的情況下。 –