Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What do andi and ori do in this program?

Tags:

assembly

mips

        .global main            # makes label "main" globally known

        .text                   # Instructions follow
        .align  2               # Align instructions to 4-byte words

main:   movi    r16,0x47        # Load the hexadecimal value 41
                                # to register r16

loop:   mov     r4,r16          # Copy to r4 from r16

        nop                     # (later changed to call hexasc)
        nop                     # (later changed to mov r4,r2)

        movia   r8,putchar      # copy subroutine address to a register
        callr   r8              # call subroutine via register

        addi    r16, r16,1      # Add 1 to register r16
        andi    r16, r16, 0x7f  # mask with 7 bits
        ori     r16, r16, 0x20  # set a bit to avoid control chars

        br      loop            # Branch to loop

        .end                    # The assembler will stop reading here
        foo bar bletch          # comes after .end - ignored

I can understand everything, I think, except how the two instructions andi and ori work in this case. ori appears to make so that the ASCII 20 positions forward is printed but why and how?

like image 908
Niklas Rosencrantz Avatar asked Feb 19 '23 11:02

Niklas Rosencrantz


2 Answers

andi with 0x7f removes the most significant bit, which is not used by ASCII (which only uses 7 bits, or 0-128 to maps characters). 0x7f is 0111 1111 in binary. Since anything AND with 0 (the most significant bit is 0, as you can see) is 0, anything AND with 1 stays the same, the operation removes the most significant bit.

ori with 0x20 will only set the 6th bit (25). 0x20 is 0010 0000 in binary. Since anything OR with 1 (the 6th bit, as you can see) is 1, and anything OR with 0 stays the same, it results in setting the 6th bit.

As the comment says, just in case r16 originally is less than 32, or in case r16 >= 128 and < 160, it will make the number >= 0x20. It doesn't mean that it will always add 0x20, though (e.g. r16 originally is 32 --addi--> 33 --andi--> 33 --ori--> 33).

As side note, AND'ing with a constant (which is also called mask) is usually for extracting certain bit out of the original data. And it will extract at whichever bit that the corresponding bit in the mask is 1.

OR'ing with constant is usually for set certain bit(s) to 1. It will set the bit whose corresponding bit in the mask is 1.

By the way, to set certain bit to 0, you can AND with constant that is all 1 except the bit that you want to set. To toggle certain bits, you can XOR with the constant with corresponding bit 1 and the rest 0.

like image 52
nhahtdh Avatar answered Feb 21 '23 23:02

nhahtdh


Using and in assembly is a way to ensure a bit is off. Consider:

1101 and
0111
---------
0101

Only in the second and the last columns do the 1s exist in the top AND the bottom, effectively ensuring that the first bit is turned off.

Using 'or' in assembly is a way to ensure that a bit is on. consider:

1101 or
0111
----------
1111

The 1s on the bottom row ensure that no matter what the first number is, the last three bits will be on.

like image 26
Bryan Wolfford Avatar answered Feb 21 '23 23:02

Bryan Wolfford