【问题标题】:Generating a random number within range of 0-9 in x86 8086 Assembly在 x86 8086 程序集中生成 0-9 范围内的随机数
【发布时间】:2013-07-25 05:11:15
【问题描述】:

首先,我对 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.我们在 12 月 10 日搬到了 CX。 4.我们将 AX 除以 CX,因此我们在 12 月 0-9 日内得到一个余数,该余数存储在 DX 中 5.最后,我们将 ASCII '0'(dec 48)添加到 DX 以将它们转换为 ASCII '0' 到 '9' .

【问题讨论】:

  • 您希望输出在 1-10(如您的标题所示)或 0-255(如您的问题所示:...生成一个字节的随机数)?代码看起来像是在尝试以 ASCII 格式执行 09 的范围。
  • 是的,如标题所示,准确地说是 0-9。

标签: assembly random x86 x86-16


【解决方案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'

您当然可以对每个随机数生成器使用此方法。

【讨论】:

  • 我尝试了你的代码,它运行良好。与我的相比,生成所需的时间也更少。但我不完全理解一些事情。 1. xor dx, dx - 这是什么目的? 2. add dl, '0' - 如何通过在 DL 中添加 '0' 我们实际实现 0-9 的 ASCII 值?
  • 我们不是给dl加0(零),而是字符“0”=30h=48的ascii码。这样,DL中的数字(从0到9)就会翻转到 30h 到 39h,它们是从“0”到“9”的字符。总是 xor something = 0。
  • 我明白了,我们做了什么: 1.我们将 DX 中的价值转移到 AX 2.我们清除了 DX。 3.我们在 12 月 10 日搬到了 CX。 4.我们将 AX 除以 CX,因此我们在 12 月 0-9 日内得到一个余数,该余数存储在 DX 中 5.最后,我们将 ASCII '0'(dec 48)添加到 DX 以将它们转换为 ASCII '0' 到 '9' .好的,谢谢
【解决方案2】:

我为这项工作找到了一个较小的操作码 AAM - Ascii Adjust for Multiplication。这个操作码是如何工作的:

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

所以,应该是这样的:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-20
    • 1970-01-01
    • 1970-01-01
    • 2010-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-20
    相关资源
    最近更新 更多