Computer Architecture Lab/Winter2007/SHWH/Assembler description

Tante Emma Assembler
Version 1.3

Assembler Usage
First 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
TanteEmmaAssembler_v_1_3.zip with example asm files and binary files

example assembler files

example binary and list files

Assembler Syntax
Our 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
 * 1) define EXAMPLE_REG	R0


 * defining integer constants
 * 1) define MY_CONSTANT	100


 * defining hex constants
 * 1) define MY_CONSTANT 0xAA

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
 * load immedate low and high

LDIL(R2,0xAA) //load unsigned immedate as hex value LDIH(R2,0x01) //load the upper byte into the register

ADD(Rx,Ry)	//Rx = Rx + Ry
 * Add two Registers

ADC(Rx,Ry)	//Rx = Rx + Ry + C
 * Add with carry

SUB(Rx,Ry)	//Rx = Rx - Ry
 * Sub

SBC(Rx,Ry)	//Rx = Rx - Ry - C
 * Sub with carry

AND(Rx,Ry)	//Rx = Rx and Ry
 * And

OR(Rx,Ry)	//Rx = Rx or Ry
 * or

XOR(Rx,Ry)	//Rx = Rx xor Ry
 * xor

SHL(Rx)
 * shift left

SHR(Rx)
 * shift right

ASR(Rx)
 * arithmic shift right

ROL(Rx)
 * Rotate left through carry

ROR(Rx)
 * Rotate right through carry

NEG(Rx)
 * 2th Complement

INC(Rx)
 * Increment Register x

DEC(Rx)
 * Decrement Register x

CLR(Rx)
 * Clear Register x

SET(Rx)
 * Set Register 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)
 * Call procedure at ProgrammCounter(PC) x

Jump to the Programm address which is saved in Register x JUMP(Rx)
 * Jump

RET
 * Return from Procedure Call

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
 * Compare two registers

BRZ(6)		//Branch PC + 6 BRZ(-4)		//Branch PC - 4 BRZ(0x04)	//Branch with hex value
 * Branch if zero

BRNZ(-6)
 * Branch if not zero

BRL(-6)
 * Branch if less

BRNL(-6)
 * Branch if not less

BRG(-6)
 * Branch if greater

BRNG(-6)
 * Branch if not greater

MOV(Rx,Ry) Rx = Ry
 * Move Reg y to Reg x

the load is Register Direct, so the memory address is saved in Register z LDIL(Rz,0x0F) LD(Rx,Rz) //Rx = (Rz)
 * Load from Memory

ST(Rz,Rx)	//(Rz) = Rx, in Rz the memory address is saved
 * Store to Memory

IN(Rx,Rz)	//Rx = [Rz], in Rz the pin number is saved
 * In from I/O

OUT(Rx,Rz)	//[Rz] = Rx, in Rz the pin number is saved
 * OUT to I/O

NOP
 * No operation

Example Assembler Code

 * Fast Blinking Led


 * 1) 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

This program sends Hello World to the console.
 * Hello World

//DemoProgramm für CA //Hello World //Write Hallo World to the console


 * 1) define REG_UART_TX_RX_NR		R2
 * 2) define UART_TX_NR				178
 * 3) define UART_RX_NR				153


 * 1) define A_H	0x48
 * 2) define A_e	0x65
 * 3) define A_l	0x6C
 * 4) define A_o	0x6F
 * 5) define A_W	0x57
 * 6) define A_r	0x72
 * 7) define A_d	0x64
 * 8) define SPACE	0x20
 * 9) 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


 * 1) define REG_UART_TX_RX_NR		R1
 * 2) define UART_TX_NR				178
 * 3) define UART_RX_NR				153


 * 1) define LED_PIN_NR	166


 * 1) define REG_IN_ALPHA			R2
 * 2) define REG_MEM_ADR				R3
 * 3) define REG_LF					R4


 * 1) define A_W	0x57
 * 2) 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

//DemoProgramm für CA //Multipliation of 2 16 bit values
 * Add two 16 bit Numbers


 * 1) define REG_UART_TX_RX_NR		R8
 * 2) define UART_TX_NR				178
 * 3) define UART_RX_NR				153


 * 1) define REG_UART_TX_NR R8


 * 1) define LED_PIN_NR     166


 * 1) define REG_PRODUCT_H  R1
 * 2) define REG_PRODUCT_L  R2


 * 1) define REG_FACTOR1    R3
 * 2) define FACTOR1_H      0xFF
 * 3) define FACTOR1_L      0xFF


 * 1) define REG_FACTOR2    R4
 * 2) define FACTOR2_H      0xFF
 * 3) define FACTOR2_L      0xFF


 * 1) define REG_COUNTER    R9


 * 1) define REG_SHIFT      R10
 * 2) define CNT_SHIFT      8


 * 1) define REG_SEND       R11
 * 2) define HELP			R12
 * 3) define STOP 			R13
 * 4) define COUNT1			R14
 * 5) 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)

//DemoProgramm für CA //Multipliation of 2 16 bit values
 * Mulitply two 16 bit Numbers


 * 1) define REG_UART_TX_NR	R8
 * 2) define UART_TX_NR	178
 * 3) define UART_RX_NR	153
 * 4) define LED_PIN_NR	166


 * 1) define REG_PRODUCT_H	R1
 * 2) define REG_PRODUCT_L	R2


 * 1) define REG_FACTOR1	R3
 * 2) define FACTOR1_H	0xAA
 * 3) define FACTOR1_L	0xAA


 * 1) define REG_FACTOR2	R4
 * 2) define FACTOR2_H	0x00
 * 3) define FACTOR2_L	0x02


 * 1) define REG_COUNTER	R9


 * 1) define REG_SHIFT	R10
 * 2) define CNT_SHIFT	8


 * 1) define REG_SEND	R11
 * 2) 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)

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)
 * Bubble Sort

//Bubblesort //Bubblesort


 * 1) define REG_UART_TX_RX_NR		R2
 * 2) define UART_TX_NR				178
 * 3) define UART_RX_NR				153


 * 1) define STOP R10
 * 2) define SORT1 R11
 * 3) define SORT2 R12
 * 4) define SORT3 R13
 * 5) define SORT4 R14
 * 6) define SORT5 R15
 * 7) define LENGTH R6
 * 8) define COUNT1 R10
 * 9) define COUNT2 R9
 * 10) define HELP R8
 * 11) define SPRUNG1 R7
 * 12) define BOOLV R5
 * 13) 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