Computer Architecture Lab/Winter2007/SHWH/Assembler description
Tante Emma Assembler
editVersion 1.3
Assembler Usage
editFirst of all, include your .asm file in TanteEmmaAsmProject.h (For example #include "myFirstAsmFile.asm"). Then you should compile the assembler project with "make all". This is already successfully tested under Windows XP and Linux. If you have already written your assembler file, for example named "myFirstAsmFile.asm", call TanteEmmaAsm myFirstAsmFile to get the binary input file for the processor.
Assembler Files
editTanteEmmaAssembler_v_1_3.zip with example asm files and binary files
Assembler Syntax
editOur assembler does instructionword generation very simple. We use simple C Makros to define our Instruction set. So the assembler syntax is different to other ones:
- Comments
//a Comment
- Redifining Registers
#define EXAMPLE_REG R0
- defining integer constants
#define MY_CONSTANT 100
- defining hex constants
#define MY_CONSTANT 0xAA
- load immedate low and high
when loading immedaite low, the processor does sign extention, so a signed immediate can be loaded in one cycle
LDIL(R1,-100) //load a signed immedate within one cycle LDIL(R2,0xAA) //load unsigned immedate as hex value LDIH(R2,0x01) //load the upper byte into the register
- Add two Registers
ADD(Rx,Ry) //Rx = Rx + Ry
- Add with carry
ADC(Rx,Ry) //Rx = Rx + Ry + C
- Sub
SUB(Rx,Ry) //Rx = Rx - Ry
- Sub with carry
SBC(Rx,Ry) //Rx = Rx - Ry - C
- And
AND(Rx,Ry) //Rx = Rx and Ry
- or
OR(Rx,Ry) //Rx = Rx or Ry
- xor
XOR(Rx,Ry) //Rx = Rx xor Ry
- shift left
SHL(Rx)
- shift right
SHR(Rx)
- arithmic shift right
ASR(Rx)
- Rotate left through carry
ROL(Rx)
- Rotate right through carry
ROR(Rx)
- 2th Complement
NEG(Rx)
- Increment Register x
INC(Rx)
- Decrement Register x
DEC(Rx)
- Clear Register x
CLR(Rx)
- Set Register x
SET(Rx)
- Call procedure at ProgrammCounter(PC) x
Before we can call the prozedure, we have to load the PC value into a Regiser
LDIL(R1,0xF0) LDIH(R1,0x00) ... CALL(R1)
- Jump
Jump to the Programm address which is saved in Register x
JUMP(Rx)
- Return from Procedure Call
RET()
- Compare two registers
the operation will manipulate the zero, less and greater flag. You can use this instruction in combination with the branch instructions.
CMP(Rx,Ry) BR..(..)
- Compare two registers
if the two registers are equal than skip the next instruction
CMPSKIP(Rx,Ry) ... //jump here if false ... //jump here if true
- Branch if zero
BRZ(6) //Branch PC + 6 BRZ(-4) //Branch PC - 4 BRZ(0x04) //Branch with hex value
- Branch if not zero
BRNZ(-6)
- Branch if less
BRL(-6)
- Branch if not less
BRNL(-6)
- Branch if greater
BRG(-6)
- Branch if not greater
BRNG(-6)
- Move Reg y to Reg x
MOV(Rx,Ry) Rx = Ry
- Load from Memory
the load is Register Direct, so the memory address is saved in Register z
LDIL(Rz,0x0F) LD(Rx,Rz) //Rx = (Rz)
- Store to Memory
ST(Rz,Rx) //(Rz) = Rx, in Rz the memory address is saved
- In from I/O
IN(Rx,Rz) //Rx = [Rz], in Rz the pin number is saved
- OUT to I/O
OUT(Rx,Rz) //[Rz] = Rx, in Rz the pin number is saved
- No operation
NOP()
Example Assembler Code
edit- Fast Blinking Led
#define LED_PIN_NR 166 LDIL( R4, LED_PIN_NR) LDIH( R4, 0) LDIL( R5, 0xFF) LDIL( R2, 0xFF) LDIL( R1, 0xFF) DEC( R1) BRNZ( -2) DEC( R2) BRNZ( -2) XOR( R3, R5) OUT( R3, R4) AND( R0, R0) BRZ( -10) NOP() NOP() NOP()
- Hello World
This program sends Hello World to the console.
//DemoProgramm für CA //Hello World //Write Hallo World to the console #define REG_UART_TX_RX_NR R2 #define UART_TX_NR 178 #define UART_RX_NR 153 #define A_H 0x48 #define A_e 0x65 #define A_l 0x6C #define A_o 0x6F #define A_W 0x57 #define A_r 0x72 #define A_d 0x64 #define SPACE 0x20 #define LF 0x0A LDIL(REG_UART_TX_RX_NR,UART_TX_NR) LDIH(REG_UART_TX_RX_NR,0) LDIL(R1,A_H) LDIH(R1,0) NOP() OUT(R1,REG_UART_TX_RX_NR) LDIL(R1,A_e) LDIH(R1,0) NOP() OUT(R1,REG_UART_TX_RX_NR) LDIL(R1,A_l) LDIH(R1,0) NOP() OUT(R1,REG_UART_TX_RX_NR) LDIL(R1,A_l) LDIH(R1,0) NOP() OUT(R1,REG_UART_TX_RX_NR) LDIL(R1,A_o) LDIH(R1,0) NOP() OUT(R1,REG_UART_TX_RX_NR) LDIL(R1,SPACE) LDIH(R1,0) NOP() OUT(R1,REG_UART_TX_RX_NR) LDIL(R1,A_W) LDIH(R1,0) NOP() OUT(R1,REG_UART_TX_RX_NR) LDIL(R1,A_o) LDIH(R1,0) NOP() OUT(R1,REG_UART_TX_RX_NR) LDIL(R1,A_r) LDIH(R1,0) NOP() OUT(R1,REG_UART_TX_RX_NR) LDIL(R1,A_l) LDIH(R1,0) NOP() OUT(R1,REG_UART_TX_RX_NR) LDIL(R1,A_d) LDIH(R1,0) NOP() OUT(R1,REG_UART_TX_RX_NR) NOP() BRNZ(-1) //endless loop NOP()
- Reverse Text
Here is an example code which is receiving x bytes from UART. When the Programm receives a LF then the programm returns the received String in reverse Order.
//DemoProgramm für CA //Reverse Text #define REG_UART_TX_RX_NR R1 #define UART_TX_NR 178 #define UART_RX_NR 153 #define LED_PIN_NR 166 #define REG_IN_ALPHA R2 #define REG_MEM_ADR R3 #define REG_LF R4 #define A_W 0x57 #define LF 0x0A LDIL(REG_LF,LF) LDIH(REG_LF,0) //receive one byte LDIL(REG_UART_TX_RX_NR, UART_RX_NR) LDIH(REG_UART_TX_RX_NR,0) //label RX NOP() IN(REG_IN_ALPHA,REG_UART_TX_RX_NR) NOP() ST(REG_MEM_ADR,REG_IN_ALPHA) INC(REG_MEM_ADR) CMP(REG_IN_ALPHA,REG_LF) //when we receive a LF Rx is over BRNZ(-7) //switch led on begin LDIL(R13,LED_PIN_NR) LDIH(R13,0) LDIL(R14,1) OUT(R14,R13) //switch led on end //switch UART to Send LDIL(REG_UART_TX_RX_NR, UART_TX_NR) LDIH(REG_UART_TX_RX_NR,0) //switch to the last alpha unequl to \n DEC(REG_MEM_ADR) DEC(REG_MEM_ADR) //label TX NOP() LD(REG_IN_ALPHA,REG_MEM_ADR) DEC(REG_MEM_ADR) NOP() NOP() OUT(REG_IN_ALPHA,REG_UART_TX_RX_NR) CMP(REG_MEM_ADR,R0) BRNZ(-7) //send last alpha LD(REG_IN_ALPHA,REG_MEM_ADR) NOP() OUT(REG_IN_ALPHA,REG_UART_TX_RX_NR) CMP(R0,R0) BRZ(-31) //Jump to begin of Programm NOP()
- Add two 16 bit Numbers
//DemoProgramm für CA //Multipliation of 2 16 bit values #define REG_UART_TX_RX_NR R8 #define UART_TX_NR 178 #define UART_RX_NR 153 #define REG_UART_TX_NR R8 #define LED_PIN_NR 166 #define REG_PRODUCT_H R1 #define REG_PRODUCT_L R2 #define REG_FACTOR1 R3 #define FACTOR1_H 0xFF #define FACTOR1_L 0xFF #define REG_FACTOR2 R4 #define FACTOR2_H 0xFF #define FACTOR2_L 0xFF #define REG_COUNTER R9 #define REG_SHIFT R10 #define CNT_SHIFT 8 #define REG_SEND R11 #define HELP R12 #define STOP R13 #define COUNT1 R14 #define COUNT2 R14 LDIL(REG_SHIFT,CNT_SHIFT) LDIL(REG_UART_TX_NR,UART_TX_NR) LDIH(REG_UART_TX_NR,0) LDIL(REG_PRODUCT_H,0) LDIH(REG_PRODUCT_H,0) LDIL(REG_PRODUCT_L,0) LDIH(REG_PRODUCT_L,0) LDIL(REG_COUNTER,0x00) LDIH(REG_COUNTER,0x00) LDIL(REG_FACTOR1,FACTOR1_L) LDIH(REG_FACTOR1,FACTOR1_H) LDIL(REG_FACTOR2,FACTOR2_L) LDIH(REG_FACTOR2,FACTOR2_H) // ************************** main *********************** LDIL(STOP,0x0A) LDIH(STOP,0) CLR(COUNT1) LDIL(REG_UART_TX_RX_NR,153) LDIH(REG_UART_TX_RX_NR,0) //-------read first number-------- IN(HELP, REG_UART_TX_RX_NR) LDIH(HELP,0) NOP() ST(COUNT1, HELP) NOP() INC(COUNT1) CMP(HELP, STOP) BRNZ(-8)//39 DEC(COUNT1) //remove Line feed MOV(COUNT2,COUNT1) //-------read second number-------- IN(HELP, REG_UART_TX_RX_NR) LDIH(HELP,0) NOP() ST(COUNT2, HELP) NOP() INC(COUNT2) CMP(HELP, STOP) BRNZ(-8)//39 LDIL(REG_SHIFT,CNT_SHIFT) CLR(COUNT1) LD(HELP,COUNT1) NOP() DEC(REG_SHIFT) SHL(HELP) CMP(REG_SHIFT,R0) BRNZ(-4) NOP() INC(COUNT1) LD(REG_FACTOR1,COUNT1) NOP() ADD(REG_FACTOR1,HELP) LDIL(REG_SHIFT,CNT_SHIFT) INC(COUNT1) LD(HELP,COUNT1) CMP(0,0) NOP() DEC(REG_SHIFT) SHL(HELP) CMP(REG_SHIFT,R0) BRNZ(-4) NOP() INC(COUNT1) LD(REG_FACTOR2,COUNT1) CMP(0,0) NOP() ADD(REG_FACTOR2,HELP) LDIL(REG_UART_TX_RX_NR,178) LDIH(REG_UART_TX_RX_NR,0) /* MOV(REG_SEND,REG_FACTOR1) OUT(REG_SEND,REG_UART_TX_NR) NOP() MOV(REG_SEND,REG_FACTOR2) NOP() OUT(REG_SEND,REG_UART_TX_NR) NOP()*/ //label: add MOV(REG_PRODUCT_L,REG_FACTOR1) //carry auf Produkt High übertragen ADD(REG_PRODUCT_L,REG_FACTOR2) ADC(REG_PRODUCT_H,0) CLR(REG_FACTOR2) CLR(REG_FACTOR1) //send high byte high but before shift right 8 times NOP() MOV(REG_SEND,REG_PRODUCT_H) LDIL(REG_SHIFT,CNT_SHIFT) DEC(REG_SHIFT) SHR(REG_SEND) CMP(REG_SHIFT,R0) BRNZ(-4) NOP() OUT(REG_SEND,REG_UART_TX_NR) NOP() MOV(REG_SEND,REG_PRODUCT_H) //send high byte low NOP() OUT(REG_SEND,REG_UART_TX_NR) NOP() //send low byte high but before shift right 8 times NOP() MOV(REG_SEND,REG_PRODUCT_L) LDIL(REG_SHIFT,CNT_SHIFT) DEC(REG_SHIFT) SHR(REG_SEND) CMP(REG_SHIFT,R0) BRNZ(-4) NOP() OUT(REG_SEND,REG_UART_TX_NR) NOP() MOV(REG_SEND,REG_PRODUCT_L) //send low byte low NOP() OUT(REG_SEND,REG_UART_TX_NR) //label endless loop CMP(0,0) NOP() NOP() NOP() JUMP(0) NOP() NOP() //CMP(R0,R0) //BRZ(-2)
- Mulitply two 16 bit Numbers
//DemoProgramm für CA //Multipliation of 2 16 bit values #define REG_UART_TX_NR R8 #define UART_TX_NR 178 #define UART_RX_NR 153 #define LED_PIN_NR 166 #define REG_PRODUCT_H R1 #define REG_PRODUCT_L R2 #define REG_FACTOR1 R3 #define FACTOR1_H 0xAA #define FACTOR1_L 0xAA #define REG_FACTOR2 R4 #define FACTOR2_H 0x00 #define FACTOR2_L 0x02 #define REG_COUNTER R9 #define REG_SHIFT R10 #define CNT_SHIFT 8 #define REG_SEND R11 #define REG_RECEIVE R12 // begin of Program LDIL(REG_PRODUCT_H,0) LDIH(REG_PRODUCT_H,0) LDIL(REG_PRODUCT_L,0) LDIH(REG_PRODUCT_L,0) LDIL(REG_COUNTER,0x00) LDIH(REG_COUNTER,0x00) LDIL(REG_UART_TX_NR,UART_RX_NR) LDIH(REG_UART_TX_NR,0) //receive Factor1, high Byte LDIL(REG_SHIFT,CNT_SHIFT) NOP() IN(REG_RECEIVE,REG_UART_TX_NR) DEC(REG_SHIFT) SHL(REG_RECEIVE) CMP(REG_SHIFT,R0) BRNZ(-4) //receive Factor1, low Byte NOP() IN(REG_FACTOR1,REG_UART_TX_NR) NOP() OR(REG_FACTOR1,REG_RECEIVE) //receive Factor2, high Byte LDIL(REG_SHIFT,CNT_SHIFT) NOP() IN(REG_RECEIVE,REG_UART_TX_NR) DEC(REG_SHIFT) SHL(REG_RECEIVE) CMP(REG_SHIFT,R0) BRNZ(-4) //receive Factor2, low Byte NOP() IN(REG_FACTOR2,REG_UART_TX_NR) NOP() OR(REG_FACTOR2,REG_RECEIVE) // ************************** multiplication ************* //label: mul loop INC(REG_COUNTER) ADC(REG_PRODUCT_L,REG_FACTOR1) //carry auf Produkt High übertragen ADC(REG_PRODUCT_H,R0) CMP(REG_COUNTER,REG_FACTOR2) BRNZ(-5) LDIL(REG_UART_TX_NR,UART_TX_NR) LDIH(REG_UART_TX_NR,0) //send high byte high but before shift right 8 times NOP() MOV(REG_SEND,REG_PRODUCT_H) LDIL(REG_SHIFT,CNT_SHIFT) DEC(REG_SHIFT) SHR(REG_SEND) CMP(REG_SHIFT,R0) BRNZ(-4) NOP() OUT(REG_SEND,REG_UART_TX_NR) NOP() MOV(REG_SEND,REG_PRODUCT_H) //send high byte low NOP() OUT(REG_SEND,REG_UART_TX_NR) //send low byte high but before shift right 8 times NOP() MOV(REG_SEND,REG_PRODUCT_L) LDIL(REG_SHIFT,CNT_SHIFT) DEC(REG_SHIFT) SHR(REG_SEND) CMP(REG_SHIFT,R0) BRNZ(-4) NOP() NOP() OUT(REG_SEND,REG_UART_TX_NR) NOP() MOV(REG_SEND,REG_PRODUCT_L) //send low byte low NOP() OUT(REG_SEND,REG_UART_TX_NR) //label endless loop CMP(R0,R0) BRZ(-66)
- Bubble Sort
You can send 8bit numbers to the processor via Uart, finish your input with LF (line feed ). The processor will return the these numbers in ascending order. (UART Settings: 115200 8N1)
//Bubblesort //Bubblesort #define REG_UART_TX_RX_NR R2 #define UART_TX_NR 178 #define UART_RX_NR 153 #define STOP R10 #define SORT1 R11 #define SORT2 R12 #define SORT3 R13 #define SORT4 R14 #define SORT5 R15 #define LENGTH R6 #define COUNT1 R10 #define COUNT2 R9 #define HELP R8 #define SPRUNG1 R7 #define BOOLV R5 #define NULLV R4 CLR(NULLV) CLR(BOOLV) LDIL(LENGTH,5) LDIL(SORT1,43) LDIL(SORT2,7) LDIL(SORT3,41) LDIL(SORT4,12) LDIL(SORT5,42) CLR(COUNT1) ST(COUNT1,SORT1) INC(COUNT1) ST(COUNT1,SORT2) INC(COUNT1) ST(COUNT1,SORT3) INC(COUNT1) ST(COUNT1,SORT4) INC(COUNT1) ST(COUNT1,SORT5) CLR(COUNT1) CLR(COUNT2) INC(COUNT2) LDIL(SPRUNG1,22) //Label: 22 CLR(BOOLV) LD(SORT1,COUNT1) LD(SORT2,COUNT2) CMP(SORT1,SORT2) BRL(3) //wenn gleich überspringe Vertauschen ST(COUNT1,SORT2) ST(COUNT2,SORT1) SET(BOOLV) //Label 30 BRL Sprung INC(COUNT1) INC(COUNT2) CMPSKIP(COUNT2,LENGTH) //Schleifenende erreich?? JUMP(SPRUNG1) //SchleifenEnde innerste CLR(COUNT1) CLR(COUNT2) INC(COUNT2) DEC(LENGTH) CMPSKIP(NULLV,BOOLV) JUMP(SPRUNG1) LDIL(REG_UART_TX_RX_NR,178) LDIH(REG_UART_TX_RX_NR,0) CLR(COUNT1) INC(COUNT1) //LDIL(SORT1,0x0F) //Debug LD(SORT1,COUNT1) OUT(SORT1,REG_UART_TX_RX_NR) INC(COUNT1) //LDIL(SORT1,0x1F) //Debug LD(SORT1,COUNT1) OUT(SORT1,REG_UART_TX_RX_NR) INC(COUNT1) //LDIL(SORT1,0x2F) //Debug LD(SORT1,COUNT1) OUT(SORT1,REG_UART_TX_RX_NR) INC(COUNT1) //LDIL(SORT1,0x3F) //Debug LD(SORT1,COUNT1) OUT(SORT1,REG_UART_TX_RX_NR) INC(COUNT1) //LDIL(SORT1,0x4F) //Debug LD(SORT1,COUNT1) OUT(SORT1,REG_UART_TX_RX_NR) /* LDIL(REG_UART_TX_RX_NR,153) LDIH(REG_UART_TX_RX_NR,0) LDIL(STOP,0x20) LDIH(STOP,0) CLR(COUNT1)*/ /*IN(SORT1, REG_UART_TX_RX_NR) ST(COUNT1, SORT1) NOP() INC(POINTER) CMP(READ, STOP) BRNZ(-6) LDIL(REG_UART_TX_RX_NR,178) LDIH(REG_UART_TX_RX_NR,0) OUT(SORT1,REG_UART_TX_RX_NR)*/ NOP() NOP() NOP()