简体   繁体   中英

Displaying number in Binary by shifting

I made a program in which I try to display the binary form of a number input by user. But the program isn't doing the masking correctly. What should I do to solve it?

user input in $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

UPDATE: I modified this code as suggested by dbrank0, but now it displays only one bit instead of 32 bits

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

It will be a great deal if someone can help me solve this problem.

Regards

Here's a problem:

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

If it's a zero, it doesn't get displayed because you're jumping to Loop instead of Disp . Oh look, Disp is written immediately after this instruction anyhow! Solution: get rid of the jump altogether.

Here's another problem, as dbrank0 described:

Disp:
li $v0,1
syscall

This will display the contents of $a0 as an integer. But if the bit was a 1, the value of $a0 will be 0x80000000, not 1! When you try to print 0x80000000, it'll treat it as a signed integer and print -2147483648 instead.

Here's another problem:

beq $t1,31,Exit

Firstly, this instruction is in an awkward place. Why are you checking for an exit condition after the and and shift ? You should check for it either at the start or the end, not in the middle. Furthermore, you need to check against 32 because there are 32 bits and you check before printing each bit. Currently the last bit will get chopped off as a result.


There's a clever way to make your program do less work than it needs to. Take advantage of the fact that you're displaying from left to right (ie, the most significant bit is being displayed first). When the MSB is set, it can be treated as a negative number in two's complement!

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:

Given a pointer to the end of a large-enough buffer in $a1 , and an input integer in $a0 , this function stores ASCII digits to form a string.

This uses an AND to extract the low bit. It works from low to high bits, so we store backwards from the end of a buffer, leaving an ASCII string in printing order.

.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

Note that this decrements before the first store, so you could pass it a pointer to a '\\n' at the end of a buffer.

You can of course inline this loop instead of using it as a callable function. It stops when the integer is zero instead of looping a fixed 32 times, so it doesn't print leading zeros.

This algorithm is the base2 special case of the basic
do { digit = a % base; } while(a /= base); .

If you're going to print the digits in the order they're generated, you can use

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

This would give you a branchless version of @JeffE's code. But if you care about efficiency, one system call that writes a whole string is much more efficient than 32 system calls to write 32 integers. (And of course real OSes don't have write-int system calls; that's a Mars/SPIM thing.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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