Bitwise Operations, Loops and using the terminal Eric McCreath
Integer Operations rPeANUt has a standard set of integer operations that work on 2s complement 32 signed integers. These are: addition add <RS1> <RS2> <RD> subtraction sub <RS1> <RS2> <RD> multiply mult <RS1> <RS2> <RD> divide div <RS1> <RS2> <RD> modulo mod <RS1> <RS2> <RD> ; calculates the remainder of a division negate neg <RS> <RD> ; this will invert all bits and add one There is also a set of operations that work on the bits of words in registers. bit and and <RS1> <RS2> <RD> bit or or <RS1> <RS2> <RD> bit xor xor <RS1> <RS2> <RD> bit not not <RS> <RD> left rotate (immediate) rotate #<amount> <RS> <RD> left rotate (register) rotate <RA> <RS> <RD> ; rotate <RA> by <RA> bits ; placing the result in <RD> 2
Bit wise operations The bitwise operations can be used to manipulating the bits in a word. Common operations include: Setting a bit to 0 in a register. Setting a bit to 1 in a register. Checking a bit in a register. These can be done with 'and', 'or', and 'rotate' operations. The below code sets bit 2 at address 0x5000 to 1. load 0x5000 R1 load #0x0004 R2 or R1 R2 R1 store R1 0x5000 Take care with bits 15 to 31. load immediate will not directly work! 3
loops An infinite loop can be implemented by jumping back to an address. AVR - Assembler - avr-gcc char x = 0; std Y+1,__zero_reg__ while (1) { .L2: x++; ldd r24,Y+1 } subi r24, lo8(-(1)) std Y+1,r24 rjmp .L2 In rPeANUt loops can also be done using the jump instruction. Note in the below example we used the stack to store the x variable. This could be optimized by using a register. 0x0100 : start : load #0 R1 push R1 loop : load SP #-1 R1 add R1 ONE R1 store R1 #-1 SP jump loop 4
loops Jumps can be conditional. rPeANUt has: jump - unconditional jump jumpn - jump if negative jumpz - jump if zero jumpnz - jump if not zero The below will count to 10 and then halt. load #0 R0 ; int count = 0 load #10 R1 count : sub R0 R1 R2 ; while (count != 0) { jumpz R2 done add ONE R0 R0 : count++; jump count ; } done : 5
IO Terminal To write to the terminal just store the character to the address of the terminal IO data register (at address 0xfff0). The below code writes 3 'a's to the terminal. 0x0100 : load #'a' R3 store R3 0xfff0 store R3 0xfff0 store R3 0xfff0 To read from the terminal first check that a character is available to read from the terminal. This can be done by checking the status register of the IO terminal (address 0xfff1). Once available the character can be read from the IO data register (address 0xfff0). The below code loops until a character is available then loads it into register 1. readc : load 0xfff1 R0 jumpz R0 readc load 0xfff0 R1 6
Echo The below code will echo what is typed to the terminal back to the terminal. 0x100 : start : load 0xfff1 R0 jumpz R0 start load 0xfff0 R1 store R1 0xfff0 jump start 7
Exercises Write a program that draws a square on the output that is 9 by 9 using the '*' character (use a loop nested within another loop for this). So the program should print: ********* ********* ********* ********* ********* ********* ********* ********* ********* Extend this program so in takes as input from the terminal a number 'n' (from 1 to 9) and prints a n by n square. If you pressed 9 it would print the above square. If you pressed 3 it would print a 3 by 3 square, etc. 8
Recommend
More recommend