0

I've read numerous threads here and elsewhere online concerning this topic. Great topics regarding bit shifts (not necessarily pertaining to Assembly but the topic in general are: What are bitwise shift (bit-shift) operators and how do they work? I've gone as far as copying and pasting the code from the OP here: How do I print a binary number with an inputed integer? and making the changes that the replier had suggested and I continue to produce a string of zero's no matter what I do.

I understand what bit shifting is and how it works. Shifting to the right by 'n' divides the number by 2^n and shifting left multiplies the number by 2^n.

I had a lab that was due this past week and the third portion of it was to provide a program that would take user input, print out the binary version of it and then the hexidecimal version. Once that was done, the program was then to print out certain bits in the center of the string and produce its binary and hexidecimal version of that as well.

My original thoughts were to take the string, AND it with 0x01, print the resulting '1' or '0', and then bit shift it right by '1'. This was contained in a loop and would continue until my counter met the '32' requirement and be done with it. But I'm extremely confused as to why it prints all '0's. I've tried other versions such as:

  • shift the user input left by 31, then do the loop for each bit but inside the loop it was shifting to the right (to make up for the reversed order of bits) - failed - all zero's again

  • do the opposite from above - failed again, all zero's

I know in my head what I want to do it something like this:

(NOT CODE OBVIOUSLY)
User input is: 25 <-- store at $t0 
    Binary rep is: 0000 0000 0000 0000 0000 0000 0001 1001 # 25 in $t0

LOOP:
    AND with 0x01: 0000 0000 0000 0000 0000 0000 0000 0001 #saved to $t1

    Produces:      0000 0000 0000 0000 0000 0000 0000 0001 #saved to $t2

    Print to Console: 1 #send contents of $t2 to syscall

    Shift $t0 Right 1: 0000 0000 0000 0000 0000 0000 0000 1100 #

j LOOP (until the beq branch was met and I left the loop)

I would have thought that this would have worked. Even if it produced the result backwards, I thought I would have still received '1's in my produced string that I would have noticed and dealt with accordingly (shift the entire number left in $t0 by '31' and then performed the instructions above. Still all '0's...

Here is my code. Now again, it has become corrupted through my numerous attempts and changes. I'm just asking for some help in understanding if my approach highlighted above is completely off-base and what I can do to the sample code below to fix this.

Understand that this assignment has been turned in and I did not complete it because of my confusion. I'm looking to understand this further. I didn't complete the entire code because I was stumped on this part. So I'll just ask for the first part of this assignment.

#Read integer A from user and store it into a register
#Display the integer in binary
#Display the integer in Hex
#set Register $a0 to contain only bits 12,13,14,15 of $a0
#Display the integer in binary contained in $a0
#Display the integer in hex contained in $a0

.data

    userInput: .asciiz "Please enter your integer:\n"
    binaryInput: .asciiz "Here is the input in binary: "
    nl: .asciiz "\n\n"
    hexInput: .asciiz "Here is the input in hexidecmal: "
    binaryOutput: .asciiz "Here is the output in binary: "
    hexOutput: .asciiz "Here is the output in hexidecimal: "

.text
    main:

    #ask end-user to submit an integer value
    li $v0, 4
    la $a0, userInput
    syscall

    #read user-input
    li $v0, 5
    syscall

    #enter user input into $t0
    move $t0, $v0
    add $t1, $zero, $zero       #counter
    addi $t2, $zero, 32     #target
    sll $s1, $t0, 31        #shift left number 31 bits to s1
    li $v0, 4
    la $a0, binaryInput     #print out string to user
    syscall


loop:
    andi $s2, $s1, 1        #and 0x01 with s1 to s2
    srl $s1, $s1, 1         #shift right s1 by 1 bit
    li $v0, 1
    la $a0, ($s2)           #print digit held in s2 to screen
    syscall
    add $t1, $t1, 1         #add 1 to counter
    bne $t1, $t2, loop      #check if counter is equal to target, if not continue loop

    #exit the program 
    li $v0, 10
    syscall
Community
  • 1
  • 1
Pwrcdr87
  • 935
  • 3
  • 16
  • 36
  • The assertion that user input is 25 - was this entered in as input and coming in as a string, or was it passed as an actual value to your function? If passed as a string, you need to do some conversions on it first to get it from string to integer. Next, does the print function want a string or a number? I am guess string, in which case you need to add '0' to your binary value so that it will print correctly. – Michael Dorgan Feb 02 '17 at 19:15
  • 2
    `la $a0, ($s2)` is really odd. `la` is supposed to be like a `li` but with 0x1001 as the upper half of the number. I'm amazed this even assembled, and have to wonder what it assembled into. – harold Feb 02 '17 at 20:22
  • @MichaelDorgan Hmmm great questions! The integer is user input which I read as `li $v0, 5` in my code. At line 3 of my `loop` i am printing the integer value. I thought this would have worked? – Pwrcdr87 Feb 02 '17 at 20:22
  • @harold if you are confused on how this even assembled then I guess my code is REALLY off. Any ideas what I can do to achieve my desired result? Again, I just ran it, entered '25' when prompted and received (32) 0's as the answer... which is horribly incorrect. – Pwrcdr87 Feb 02 '17 at 20:25
  • 1
    Remove `sll` (that just throws away most bits), remove `la $a0, ($s2)` (I don't know what this ends up doing, but probably not the right thing), write the result of `andi` to `$a0`, maybe that does it, but I haven't tested it of course – harold Feb 02 '17 at 20:32
  • @harold I've done as you suggested and still receive the same answer... This is nuts. I don't even get a single '1' in my printed string. I've changed the amount the loop is performed to 45 (just to see if a '1' shows up anywhere) and changed my input to '100' still no go. Produced (45) 0's. – Pwrcdr87 Feb 02 '17 at 20:45
  • 1
    Does a non-zero number even go into that loop then? – harold Feb 02 '17 at 20:50
  • @harold AHHHHH!!!! When I made the changes you suggested I didn't realize that when I removed the `sll $s1, $t0, 31` line I removed all correlation between `$s1` within the loop. Therefore, it contained '0' which AND'ing it in the loop with '1' will always produce '0'! Now when I enter '100' when prompted, it produces `0010 0110 0000 0000 0000 0000 0000 0000`. Now I need to understand how to flip it! Excellent! +1 harold! – Pwrcdr87 Feb 02 '17 at 21:19

1 Answers1

2

Here's a method that is somewhat different from your basic approach. It treats binary output and hex output as parameters to a common output function. The bit masking/bit shifting is similar but the mask and bit width are variable.

# Read integer A from user and store it into a register
# Display the integer in binary
# Display the integer in Hex
# set Register $a0 to contain only bits 12,13,14,15 of $a0
# Display the integer in binary contained in $a0
# Display the integer in hex contained in $a0

    .data
userInput:  .asciiz     "Please enter your integer: "
binaryInput:    .asciiz "Here is the input in binary: "
nl:         .asciiz     "\n"
hexInput:   .asciiz     "Here is the input in hexadecimal: "
binaryOutput:   .asciiz "Here is the output in binary: "
hexOutput:  .asciiz     "Here is the output in hexadecimal: "
hexDigit:   .asciiz     "0123456789ABCDEF"
obuf:       .space      100
obufe:

    .text
    .globl  main
main:
    # ask end-user to submit an integer value
    li      $v0,4
    la      $a0,userInput
    syscall

    # read user-input
    li      $v0,5
    syscall
    move    $s0,$v0

    # output original in binary
    la      $a0,binaryInput
    li      $a1,32
    jal     prtbin

    # output original in hex
    la      $a0,hexInput
    li      $a1,32
    jal     prthex

    # isolate bits 12,13,14,15
    srl     $s0,$s0,12
    andi    $s0,$s0,0x0F

    # output isolated in binary
    la      $a0,binaryOutput
    li      $a1,4
    jal     prtbin

    # output isolated in hex
    la      $a0,hexOutput
    li      $a1,4
    jal     prthex

    # exit the program
    li      $v0,10
    syscall

# prtbin -- print in binary
#
# arguments:
#   a0 -- output string
#   a1 -- number of bits to output
prtbin:
    li      $a2,1                   # bit width of number base digit
    j       prtany

# prthex -- print in hex
#
# arguments:
#   a0 -- output string
#   a1 -- number of bits to output
prthex:
    li      $a2,4                   # bit width of number base digit
    j       prtany

# prtany -- print in given number base
#
# arguments:
#   a0 -- output string
#   a1 -- number of bits to output
#   a2 -- bit width of number base digit
#   s0 -- number to print
#
# registers:
#   t0 -- current digit value
#   t5 -- current remaining number value
#   t6 -- output pointer
#   t7 -- mask for digit
prtany:
    li      $t7,1
    sllv    $t7,$t7,$a2             # get mask + 1
    subu    $t7,$t7,1               # get mask for digit

    la      $t6,obufe               # point one past end of buffer
    subu    $t6,$t6,1               # point to last char in buffer
    sb      $zero,0($t6)            # store string EOS

    move    $t5,$s0                 # get number

prtany_loop:
    and     $t0,$t5,$t7             # isolate digit
    lb      $t0,hexDigit($t0)       # get ascii digit

    subu    $t6,$t6,1               # move output pointer one left
    sb      $t0,0($t6)              # store into output buffer

    srlv    $t5,$t5,$a2             # slide next number digit into lower bits
    sub     $a1,$a1,$a2             # bump down remaining bit count
    bgtz    $a1,prtany_loop         # more to do? if yes, loop

    # output string
    li      $v0,4
    syscall

    # output the number
    move    $a0,$t6                 # point to ascii digit string start
    syscall

    # output newline
    la      $a0,nl
    syscall

    jr      $ra                     # return
Craig Estey
  • 30,627
  • 4
  • 24
  • 48
  • Thanks Craig Estey! I've ran this a few times and it appears to work perfectly. I need to dissect your code when I get an opportunity since we just learned the jumps that you are doing just a day ago, as well as how to pass arguments as you are doing. `subu` is new to me also. But this is an excellent crash course on these topics for me. – Pwrcdr87 Feb 03 '17 at 14:12
  • harold, i would have given you more points for the help you gave me initially. Unfortunately, all I could do was upvote your responses to my initial post. Sorry mate but I really appreciate you taking the time to look over my beginning code and point out certain areas where I was going wrong. – Pwrcdr87 Feb 03 '17 at 14:13