-1

我制作了一个程序,尝试显示用户输入的数字的二进制形式。但是程序没有正确地进行掩蔽。我应该怎么做才能解决它?

$s0 中的用户输入

Loop:

and $t0,$s0,2147483648  // anding it with this number because only its MSB is 1 all other bits are zero

sll $s0,$s0,1

move $a0,$t0

li $v0,1
syscall

beq $t1,31,Exit

addi $t1,$t1,1
j Loop

更新: 我按照 dbrank0 的建议修改了这段代码,但现在它只显示一位而不是 32 位

Loop:

and $t0,$s0,2147483648

sll $s0,$s0,1

beq $t1,31,Exit

move $a0,$t0

addi $t1,$t1,1

bgtu $t0,0,Check

li $t0,0
j Loop

Disp:
li $v0,1
syscall

j Loop

Check:
li $t0,1

j Disp

如果有人可以帮助我解决这个问题,那将是一件好事。

问候

4

2 回答 2

3

这里有一个问题:

bgtu  $t0, 0, Check
li    $t0, 0
j     Loop

如果它是零,则不会显示,因为您要跳转到Loop而不是Disp. 哦,看,Disp反正是在这个指令之后立即写的!解决方案:完全摆脱跳跃。

这是另一个问题,如 dbrank0 所述:

Disp:
li $v0,1
syscall

这会将 的内容显示$a0为整数。但如果该位为 1,则值为$a00x80000000,而不是 1!当您尝试打印 0x80000000 时,它会将其视为有符号整数并改为打印 -2147483648。

这是另一个问题:

beq $t1,31,Exit

首先,这个指令是在一个尴尬的地方。and为什么要在and之后检查退出条件shift?您应该在开始或结束时检查它,而不是在中间。此外,您需要检查 32,因为有 32 位,并且您在打印每个位之前进行检查。目前,最后一位将因此被砍掉。


有一个聪明的方法可以让你的程序做的工作比它需要的少。利用您从左到右显示的事实(即首先显示最高有效位)。当设置了 MSB 时,可以将其视为二进制补码中的负数!

li     $t0, 32
li     $v0, 1

Loop:
bltz   $s0, Bit1
li     $a0, 0
j      Disp

Bit1:
li     $a0, 1

Disp:
syscall

Tail:
subi   $t0, $t0, 1
beqz   $t0, Exit
sll    $s0, $s0, 1
j      Loop

Exit:
于 2012-10-09T17:30:21.537 回答
0

给定一个指向 中足够大的缓冲区末尾的指针$a1和 中的输入整数$a0,此函数存储 ASCII 数字以形成字符串。

这使用 AND 来提取低位。它从低位到高位工作,所以我们从缓冲区的末尾向后存储,留下一个 ASCII 字符串以打印顺序。

.globl to_base2_end    # args: (unsigned a, char *buf_end)
to_base2_end:

  # Runs at least once, so we get "0" instead of the empty string for 0
.loop:                           # do {
    andi  $t0,  $a0, 1           #    extract the low bit
    ori   $t0,  $t0, '0'         #    ASCII digit

    addiu $a1,  $a1, -1
    sb    $t0,  ($a1)            #    *--buf = ASCII digit

    srl   $a0,  $a0, 1           #    a0 >>= 1
    bne   $a0, $zero,  .loop     # }while (a0!=0);

    move  $v0, $a1           # return pointer to the first digit
    jr   $ra

请注意,这在第一次存储之前递减,因此您可以将指针传递给'\n'缓冲区末尾的 a 。

您当然可以内联此循环,而不是将其用作可调用函数。它在整数为零时停止,而不是循环固定 32 次,因此它不会打印前导零。

该算法是基本的 base2 特例
do { digit = a % base; } while(a /= base);

如果您要按生成的顺序打印数字,您可以使用

    slt   $t0,  $a0, $zero       #    t0 = 0 or 1 = high bit of a0
    sll   $a0,  $a0, 1

这将为您提供@JeffE 代码的无分支版本。但是,如果您关心效率,写入整个字符串的一个系统调用比写入 32 个整数的 32 个系统调用要高效得多。(当然,真正的操作系统没有 write-int 系统调用;那是 Mars/SPIM 的事情。)

于 2017-10-04T21:14:33.040 回答