Search code examples
assemblybit-manipulationmips32

How do I manipulate bits in Assembly language MIPS32


I am having a little bit of trouble figuring this out for the 1st two parts with the "xxxxxxx" I have

add $t0, $v0, $0        # $t0 gets copy of input x
sub $t1, $0, $t0        # $t1 gets mask1 that is "-x"

but the rest I am confused. I do not want an exact answer but an explanation will help immensely!

UPDATE:

I was able to make it work. Here is the solution. Thank you!

**move $t0, $v0**           # $t0 gets copy of input x
**sub $t1, $zero, $t0**     # $t1 gets mask1 that is "-x"

li $v0, 1
move $a0, $t0
syscall

li $v0, 4
la $a0, outLab1        
syscall                # print output label 1
li $v0, 1
**and $a0, $t0, $t1**      # $a0 gets "all bits of x cleared except the 
                         rightmost 1"
syscall

not $t2, $a0           # $t2 gets mask2 that is "$a0 with all its bits 
                         toggled"

li $v0, 4
la $a0, outLab2        
syscall                # print output label 2
li $v0, 1
**and $a0, $t0, $t2**      # $a0 gets "all bits of x with the rightmost 1 
                           cleared"
syscall

li $v0, 10               # exit
syscall

Solution

  •     xxxxxxxxxxxxx   #$a0 gets "all bits of x cleared except the rightmost 1"
    

    Check how two's complement works, and how the value x looks (bitwise) both in t0 and t1 (-x). There's one very basic bitwise operation, which when applied to x and -x will produce exactly just 1 bit set (special case is the 0x80000000 (-2147483648) input, for which the negated value is out of 32 bit signed integer range, the +2147483648 is again 0x80000000 (in 32 bit unsigned integer), i.e. collides with -2147483648 representation of 32b signed integers. That's why 32b int has range -2147483648 to +2147483647 only).

        xxxxxxxxxxxxx   # $t2 gets mask2 that is "$a0 with all its bits toggled"
    

    Well, just toggle each bit? (As I don't do MIPS programming, I'm not sure which instruction can be used on MIPS, on x86 the NOT would do). So check through the MIPS instruction set, bitwise operations probably. On CPUs without some kind of built-in NOT you can do this by using xor (sometimes called eor) and the constant with all bits set (-1 or ~0 in C, in assemblers usually -1 works too). I think on some RISC CPUs the zero register can be flipped + used in single instruction, as source of -1 too. I'm adding this sh*t just to show you, that you need to be a bit creative in assembly, being aware of all instructions and values in registers, to take some shortcut for some particular arithmetic result.

        xxxxxxxxxxxx    # $a0 gets "all bits of x with the rightmost 1 cleared"
    

    Now they ask you to clear the rightmost 1 and keep all the other bits intact, of original value x. I don't see how to help you with this one without revealing the solution instantly, as it's absolutely trivial, if you think about what your t0, t1 and t2 contains at this point.

    Maybe you have problem to see those values in binary form, so it doesn't "jump at you" how these things works? Try some calculator, which can display binary form too, and check the calculations/values to see particular bits (switch back and forth between decimal, hexadecimal and binary, especially the hex<->bin is nice to understand, then you can "see" the particular bits in head just by reading the hexadecimal formatting of value), then re-read the description of basic bitwise operations (and, or, xor), and get back to this task.