Reference: C to Assembly Patterns

This will be a quick reference page to clearly associate high level code constructs to assembly language. These are only one example of how to achieve the result, there are usually many others.

Bit Shift

Bit shifting in assembly language is commonly used instead of multiplication and division. The downside is it's only powers of 2 but that is also a common scenario when twiddling bits.

Assembly

slr t0, t1, 2

C

t0 = t1 / 4;

Assembly

sll t0, t1, 2

C

t0 = t1 * 4

Bit Manipulation

Bit manipulation is useful for testing if a specific bit is either a zero or one. Also can be used on groups or patterns of bits. Standard 'Truth Tables' apply.

Common usages

  • AND - Using a mask to check the state of a single or group of bits

  • OR -

  • NOR

  • XOR

Conditions

Think of the 'b' or branch instructions as the '(test == true) -> else'. It took me a while to think like this.

  • Test ex. beq t1, r0, label

  • if true go to label

  • if false continue to the instruction after the delay slot.

beq t1, r0, label

nop

add t1, t1, 1

label:

nop

add t1, t1, 2

C equivalent:

if (t1 != r0) // <= Inverted

{

t1 = t1 + 1;

}

else

{

t1 = t1 + 2

}

This is inverted logic for most programmers, hopefully the '(test == true) -> else' idea helps.

There are a few things to note about Branches. Trying to perform a branch condition in a single instruction is actually a bit limited. From the table below it's clear there are a lot of instruction options 16 in fact, what takes a second look is that there are no "immediate" comparison options, and if the condition isn't 'equal' or 'not equal' then it compares to zero. The best advice is find a way to compare against zero, there are many cases it can be difficult, but it's worth a little effort.

Psuedo Instructions

Always: Always executes the Delay Slot

Conditional: Only executes the Delay Slot if Branch is taken

Uses $ra: Sets the $ra Register so the Branch can return to that location

Conditional and uses $ra: combines both of the above options

Notes:

  • BEQ* and BNE are 2 register instructions

  • BL* and BG* instructions use a signed value in a single register

  • The BLE* instructions use the sign bit = 1 and <> zero.

  • The BLT* instructions use the sign bit = 1.

  • The BGE* instructions use the sign bit = 0.

  • The BGT* instructions use the sign bit = 0 and <> zero

In order of branching performance choice:

  1. Compare Equal or not equal

    1. bne or beq

  2. Compare against zero

    1. all of the other instructions

  3. if you need a > or < combination

    1. use a setl instruction to perform the comparison with a result of zero

  4. If you want an 'immediate' type of compare

    1. 16bit or smaller use 'addi t0, r0, value'

    2. Greater than 16bit use the li or la psuedo instruction

  5. Load Register comparison value from RAM

Function Calls

j, jr - is a jump that is not coming back to the source location

  • Jump from initialization code to loop code

jal, jalr - saves it's source location in $ra and can return easily

  • Used for Function Calls

References

http://www.cs.umd.edu/class/spring2003/cmsc311/Notes/index.html