You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MIPS汇编输出错误随机位,无法替换syscall41为42的问题

Mars MIPS汇编生成随机位异常解决

问题分析

  1. syscall 41输出全1:Mars中syscall 41用于生成32位随机整数,但如果未先初始化随机数生成器,默认会返回-1(二进制全1),取最低位后自然每次得到1,导致输出全1序列。
  2. syscall 42报错:syscall 42用于生成指定范围的随机数,要求$a1传入正整数作为上界(生成范围为[0, $a1-1])。直接修改syscall编号但未设置$a1参数,寄存器中残留的垃圾值(可能为负数)会触发"Upper bound cannot be negative"错误。

解决方案

必须先初始化随机数生成器,再选择正确的syscall生成随机位:

方案1:修复syscall 41的使用

先调用syscall 40初始化随机数生成器(可使用当前时间或固定值作为种子),再用syscall 41生成随机数并取最低位。

方案2:正确使用syscall 42生成0/1随机位

syscall 42传入上界2,直接生成0或1的随机数,无需额外处理即可作为结果返回。

修改后的完整代码

#vim:sw=2 syntax=asm
 .data
  random_id: .word 0 
     .globl main
 # Memory layout of the Configuration
 # |   eca  |   tape   |  tape_len  |  rule  |  skip  | column |
 # | 1 word |  1 word  |   1 byte   | 1 byte | 1 byte | 1 byte |
automaton:
  .word 1       # eca
  .word 252     # tape
  .byte 8       # tape_len
  .byte 106     # rule
  .byte 1       # skip
  .byte 5       # column

syscall_error_msg:
  .asciiz "Error: Random number generator syscall failed"


.text
  .globl gen_byte, gen_bit

  main:
    # 初始化随机数生成器:用当前时间作为种子
    li $v0, 40          # syscall 40 = 初始化随机数生成器
    lw $a0, random_id   # 使用默认生成器ID 0
    li $a1, 0           # 传入0表示用当前时间作为种子(Mars支持)
    syscall

# Arguments:
#     $a0 : address of configuration in memory
#   0($a0): eca       (1 word)
#   4($a0): tape      (1 word)
#   8($a0): tape_len  (1 byte)
#   9($a0): rule      (1 byte)
#  10($a0): skip      (1 byte)
#  11($a0): column    (1 byte)

# Return value:
#  Compute the next valid byte (00, 01, 10) and put into $v0
#  If 11 would be returned, produce two new bits until valid

loopcounter:
  li $s0 30 # loop counter
loop:
  beqz $s0 terminate
  subi $s0 $s0 1
  la $a0 automaton
  jal gen_bit
  # print returned value
  move $a0 $v0
  li $v0 1
  syscall
  j loop
 terminate:
  li      $v0 10
  syscall


gen_byte:
li $v0, 0

gen_byte_loop:
jal gen_bit
move $t1, $v0 # 存储第一个bit
sll $t1, $t1, 1  # 左移一位,预留第二个bit的位置
jal gen_bit
or $t1, $t1, $v0 # 合并两个bit

# 若生成11(十进制3)则重新生成
beq $t1, 3, gen_byte_loop  

gen_byte_end:
srl $t0, $t1, 1
move $v0, $t0 

  jr $ra

# Arguments:
#     $a0 : address of configuration in memory
#   0($a0): eca       (1 word)
#   4($a0): tape      (1 word)
#   8($a0): tape_len  (1 byte)
#   9($a0): rule      (1 byte)
#  10($a0): skip      (1 byte)
#  11($a0): column    (1 byte)
#
# Return value:
#  Look at the field {eca} and use the associated random number generator to generate one bit.
#  Put the computed bit into $v0

gen_bit:
  # 方案1:使用syscall41生成随机数取最低位
  li $v0, 41
  lw $a0, random_id
  syscall
  
  bltz $v0, syscall_failed
  andi $v0, $v0, 1  # 取最低位作为随机bit

  # ------------------------------
  # 方案2:使用syscall42直接生成0/1
  # li $v0, 42
  # lw $a0, random_id
  # li $a1, 2         # 上界为2,生成0或1
  # syscall
  # bltz $v0, syscall_failed
  # # $v0直接是0或1,无需额外处理
  # ------------------------------

  jr $ra

syscall_failed:
  li $v0, 4
  la $a0, syscall_error_msg
  syscall
  
  li $v0, 10
  syscall

额外说明

  • 初始化随机数生成器时,若传入固定种子(如li $a1, 1234),每次运行会得到相同的随机序列,方便调试;传入0则用当前时间作为种子,每次序列不同。
  • gen_byte函数原逻辑存在错误:仅判断00的情况,漏掉了01和10的合法情况,修改为判断是否等于3(二进制11),若为非法值则重新生成。

内容的提问来源于stack exchange,提问作者ByBlackyDZN

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 06:02:13