This semester I’m taking a RISC assembly class. I like it.
Programming in assembly is relaxing because of its simplicity. Or at least until it stops being simple. Such as today.
For a CRC calculating program I needed to be able to set a mask with the high bits set. This is tricky since the move instruction can only set the lower 13 bits. In my first attempt I used move and shift instructions to assemble the mask. This was of course messy which is why I was thankful when my friend showed me the set instruction which could set all 32 bits at once.
We puzzled at how this might be possible since that would leave no room for the opcode. The entire instruction has to be translated to 32 bits which includes the arguments to the instruction. So 32 bits of instructions should be impossible.
I decided to ignore the underlining mechanise.
Turns out ignoring what the computer is doing when you are programming in assembly is a bad idea. The set instruction does in-fact map to multiple instructions when the input is greater than 13 bits.
It just so happens that I would find this out the hard way. You see one of those high bit masks I needed was assigned in the delay slot of a branching instruction. For the laymen; a delay slot is a way to slip in an extra instruction when otherwise the cpu would do nothing. This meant that of the two instructions that set was translated too, only one of them was ran.
Thus one key portion of my bit mask was left unset.
When the mask should have been 0x80000810 it turned into only 0x80000800
Notice that the 5th bit is a zero instead of a one and so my CRC had one less xor gate than it should have.
This easily took an hour to debug. And unlike most bugs this one didn’t have an ah-ha! moment. Even when GDB clearly showed that the mask was incorrect I had to experiment to assure myself of what I was seeing.
Assembly is not very relaxing when you do not know what the computer doing.