web-dev-qa-db-ja.com

x86 8086アセンブリで0〜9の範囲内の乱数を生成する

まず第一に、私は8086アセンブリに非常に慣れていないので、知識を得るのはかなり困難でした。それでも、頑張ります。

0〜9の範囲の乱数を生成するコードを作成しようとしています。いくつかの例と提案を検討した後、これが私が最終的に得たものです。簡単にするために、取得したクロックカウントに数学関数を適用しませんでした。また、それは不要だと思いました。なんらかの理由で、1、3、9などの数値よりも6.7のような特定の数値を生成することになりました。これは、値が変化するクロックティックの下位を取っているためだと思います。急速に。

私の目的は、後でコードの範囲を1〜6に変更するダイスロールをシミュレートすることです。私の質問は、これは私の目的には十分ですか?またはこれを行うためのより良い方法はありますか?

コード:

RANDGEN:        ; generate a Rand no using the system time
RANDSTART:
   MOV AH, 00h  ; interrupts to get system time        
   INT 1AH      ; CX:DX now hold number of clock ticks since midnight      
                ; lets just take the lower bits of DL for a start..
   MOV BH, 57   ; set limit to 57 (ASCII for 9) 
   MOV AH, DL  
   CMP AH, BH   ; compare with value in  DL,      
   JA RANDSTART ; if more, regenerate. if not, continue... 

   MOV BH, 49   ; set limit to 48 (ASCII FOR 0)
   MOV AH, DL   
   CMP AH, BH   ; compare with value in DL
   JB RANDSTART ; if less, regenerate.   


   ; if not, this is what we need 
   mov ah, 2h   ; call interrupt to display a value in DL
   int 21h    
RET

@johnfoundによる回答:

彼のやり方はもっと簡単で、乱数を生成するのにかかる時間が短いことがわかりました。彼は、これは単一の乱数が必要な場合、または乱数間の間隔に人間の入力の一時停止が含まれる場合にのみ機能すると述べました。そうでない場合、数値はまったくランダムになりません(最初に取得するタイムシードのため、変更されないと思います)。私はロールダイスをシミュレートしているので、私の場合は問題ありません。コードを再度実行する前に、ユーザーの介入(別のロール)が必要です。

RANDGEN:         ; generate a Rand no using the system time
RANDSTART:
   MOV AH, 00h  ; interrupts to get system time        
   INT 1AH      ; CX:DX now hold number of clock ticks since midnight      

   mov  ax, dx
   xor  dx, dx
   mov  cx, 10    
   div  cx       ; here dx contains the remainder of the division - from 0 to 9

   add  dl, '0'  ; to ascii from '0' to '9'
   mov ah, 2h   ; call interrupt to display a value in DL
   int 21h    
RET    

彼がしたこと:1。DXの値をAXに移動しました。2。DXをクリアしました。 3.10decをCXに移動しました。 4. AXをCXで割ったため、12月0〜9日以内に剰余が得られ、DXに格納されます。5。最後に、DXにASCII '0'(dec 48))を追加して取得しました。 into ASCII '0'から '9'。

7
Raf

このトリックは、単一の乱数が必要な場合、または乱数間の間隔に人間の入力の一時停止が含まれている場合にのみ機能します。他のすべての場合、数字はまったくランダムではありません。

多くの乱数が必要な場合は、さまざまな疑似乱数アルゴリズムを利用できます。

もう1つの注意点は、必要な間隔で数値を取得するより簡単な方法があることです。

    mov  ax, dx
    xor  dx, dx
    mov  cx, 10    
    div  cx       ; here dx contains the remainder of the division - from 0 to 9

    add  dl, '0'  ; to ascii from '0' to '9'

もちろん、この方法はすべての乱数ジェネレーターに使用できます。

8
johnfound

このジョブ用に、小さいオペコードAAM-Ascii Adjust forMultiplicationを見つけました。このオペコードのしくみ:

AH := AL / 10
AL := AL mod 10

だから、それはこれになります:

mov al, dl
aam
add al, '0'
mov dl, al
0
Cat