Computer Architecture Lab/Winter2007/SHWH/Assembler description

< Computer Architecture Lab < Winter2007 < SHWH

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:

//a Comment
#define EXAMPLE_REG	R0
#define MY_CONSTANT	100
#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

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
ADC(Rx,Ry)	//Rx = Rx + Ry + C
SUB(Rx,Ry)	//Rx = Rx - Ry
SBC(Rx,Ry)	//Rx = Rx - Ry - C
AND(Rx,Ry)	//Rx = Rx and Ry
OR(Rx,Ry)	//Rx = Rx or Ry
XOR(Rx,Ry)	//Rx = Rx xor Ry
SHL(Rx)
SHR(Rx)
ASR(Rx)
ROL(Rx)
ROR(Rx)
NEG(Rx)
INC(Rx)
DEC(Rx)
CLR(Rx)
SET(Rx)

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 to the Programm address which is saved in Register x
JUMP(Rx)
RET()

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..(..)

if the two registers are equal than skip the next instruction

CMPSKIP(Rx,Ry)
...	//jump here if false
...	//jump here if true

BRZ(6)		//Branch PC + 6
BRZ(-4)		//Branch PC - 4
BRZ(0x04)	//Branch with hex value
BRNZ(-6)
BRL(-6)
BRNL(-6)
BRG(-6)
BRNG(-6)
MOV(Rx,Ry) Rx = Ry
the load is Register Direct, so the memory address is saved in Register z
LDIL(Rz,0x0F)
LD(Rx,Rz) //Rx = (Rz)
ST(Rz,Rx)	//(Rz) = Rx, in Rz the memory address is saved
IN(Rx,Rz)	//Rx = [Rz], in Rz the pin number is saved
OUT(Rx,Rz)	//[Rz] = Rx, in Rz the pin number is saved
NOP()

Example Assembler Code

#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.

//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()


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()


//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)

//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)

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()
This article is issued from Wikiversity - version of the Saturday, August 16, 2014. The text is available under the Creative Commons Attribution/Share Alike but additional terms may apply for the media files.