繁体   English   中英

通过移位显示二进制数

[英]Displaying number in Binary by shifting

我制作了一个程序,尝试显示用户输入的数字的二进制形式。 但是该程序未正确执行屏蔽。 我该怎么解决?

用户输入$ 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

如果有人可以帮助我解决这个问题,那将是非常重要的。

问候

这是一个问题:

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

如果为零,则不会显示它,因为您要跳转到Loop而不是Disp 哦,看,无论如何, Disp会在此指令后立即编写! 解决方案:完全摆脱跳跃。

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

Disp:
li $v0,1
syscall

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

这是另一个问题:

beq $t1,31,Exit

首先,该指令处于尴尬的位置。 为什么在andshift之后检查退出条件? 您应该在开头或结尾而不是在中间检查它。 此外,由于存在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:

给定一个指向$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'指针。

当然,您可以内联此循环,而不是将其用作可调用函数。 当整数为零时,它将停止,而不会循环固定的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之类的东西。)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM