Previouos chapter | Table of Contents | Next chapter →

Chapter 4: Assembly Language

From the free online book “Architecture and Programming of PSoC Microcontrollers”

 

Introduction

Complete set of 37 basic instructions, which makes with their sub-variants total number of 136 instructions, are explained in this chapter. Reason for such large number of instructions lies in the fact that this is a CISC architecture microcontroller, whose instructions allow pretty much conform programming. One disadvantages is that instructions are not optimized for speed, because their execution takes several instruction cycles.

4.1 Instruction types

Data transfer

Data transfer is done by instructions MOV, MVI and SWAP. MOV represents basic transfer instruction, which offers large number of arguments. First argument is destination location, while second source location. There are 21 types of MOV instruction in total, in dependence of data types. Shortest execution time is in the case when data is transferred trough internal registers A and X, while it is the longest when transferring contents of two variables. Instruction MVI is optimized for data transfer between accumulator A and array of sequential data locations. Aside from transferring data, at the same time initialization, which is needed for acquiring next element, takes place. One of the arguments is register A, and other is the value of variable that has a role of pointer to array, i.e. which holds address of the first array element. Instruction SWAP is used for direct exchange between registers A,X and a value of some variable Beside that, there’s also a possibility of exchange of values in registers A and SP.

Arithmetic and logic

PSoC as well as other microcontrollers has built-in support for arithmetic operations, like addition or subtraction. Instructions ADD and SUB are two basic operations. Value of the first argument is added or subtracted with other argument, and result is stored in the first value Beside basic operations of adding and subtracting, there are also existing their modifications. There are instructions INC and DEC, which implements increment (add 1) or decrement (subtract 1) operations. ADC and SBB makes addition or subtraction operation, while Carry Flag is added to the result, which allows simple multi-byte operations. MAC unit allows operation of hardware multiplication. There are no special instructions for this operation, since all the work is done in special multiplication registers. Values that are multiplying are transferred to registers MUL_X and MUL_Y with MOV instruction, and then high end, and low end bytes are read from registers MUL_DH and MUL_DL.

Logic unit of PSoC microcontroller has ability to handle standard logical operations AND, OR, XOR, negation (CPL), shifting (ASL, ASR) and rotation (RLC, RRC). For operations that have two arguments holds rule that operation is executing on according bits of both arguments, and the result is stored in first argument. In case of CPL instruction content of accumulator is completed bit by bit, so that every zero is replaced by one, and opposite. Instructions of shifting and rotation moves bits one space to the left (toward bit 7) or one space to the right (toward bit 0), while the bit that exits register is written into Carry Flag of F register. There are differences in the way how are set bit 0 or bit 7. ASL and ASR instructions are used for signed multiplication and dividing by number 2. In the case of ASL zero bit is set to 0, and in the case of ASR, bit seven is not changed. Rotation instructions RLC and RRC are writing bit exiting register Carry Flag into which is later written to bit on opposite side of register.

Comparation instructions

Because of need to compare arguments, there are two instructions CMP and TST. These instructions have two comparing arguments that don't change their value. Result of these instructions represents state of Z and C flags in F register.

Instruction CMP is used to compare two values. If both arguments are equal, Z flag will be set to one. If first argument is lower than the other C flag will be set to one, in every opposite case C and Z flags will be set to zero.

TST instruction is doing AND operation between the first argument, and eight-bit constant, during which the result is not written in first argument, like in case of AND operation. If result of AND operation is zero, then flag Z will be set to one. TST instruction gives possibility to test if certain bit of some register is set to zero or one. As eight-bit constant should be taken mask value, which has all zeroes, and one in position where are test bits. In this case, flag Z shows that bit is set to one. PSoC microcontrollers support conditional, unconditional and subprogram jumps.

Decision and Control statements

Instructions of relative jumps allow us to continue program execution from given label if condition for that jump is met, which means that appropriate flag is set - C, for jumps JC and JNC, and Z for JZ and JNZ jumps. If condition is not met, program continues to execute the next instruction.

Unconditional jumps use two sets of instructions, depending on how far jump address is. For close jumps instructions JMP and JACC are used, while instruction LJMP is used for far jumps.

Instructions JACC uses offset jump relative to given label, whose value is stored in register A.

Calling routine (CALL) and return (RET) from subprogram, as well as returning from interrupt (RETI) are executed the same way as in other microcontrollers. Instructions for stack operations Instructions PUSH and POP are, in standard ways, allowing storing values of important registers inside of stack during procedure calling. PUSH instruction is copying value of register A and X, while instruction POP returns values in opposite order. Stack is LIFO ordered, which means Last In First Out, which explains a little bit more the way PUSH and POP instructions function. Stack is positioned in upper part of RAM, so it wouldn’t overlap with defined variables. Beside holding important registers, these instructions allow transporting procedure parameters over stack, by storing parameter using PUSH before procedure call, and taking it from stack by calling PUSH instruction from inside of procedure. Instructions PUSH and POP with help of index addressing allow realization of local variables inside procedures, which will be discussed later in examples part.

Accessing ROM Data that is stored in ROM can be accessed with help of instructions INDEX and ROMX. INDEX is of special importance during look-up table reading. Offset of the element that is being accessed is previously stored in accumulator A, while the label of look-up table is called as argument. Result of read value is stored in register A.

Other instructions Of other instructions, most important one is NOP, which does no special operation, but is used for time delaying that lasts four instruction cycles.

4.2 Operators

Among instructions, where constants appear, it is possible to form statements with help of assembler operators for arithmetic and logic functions. Execution of operators has nothing with work of microcontroller, because that work is being done by compiler during program translation. Next table gives comprehensive list of assembly operators.

4.3 Constants

Decimal constants are written without any prefixes, while hexadecimal ones have prefix 0x or $, while binary ones have 0b or %. Constant character arrays are written inside of quotation marks.

4.4 Instruction set

(work in progress)

4.5 Directives

Directives represent useful elements in assembly that give various information of interest for program translation. Some of more important directives will be covered further.

DB

DB directive is convenient for look-up table forming where bytes are used as data. Binary values of constants are written inside of ROM memory at the address specified by label.

Table1: DB 1,2,3 

DW, DWL

When it is needed to form look-up tables with word type elements, then it is possible to use directives DW and DWL, depending on which byte do they store first, lower then higher or contrary.

Table2: DW 0x1234,0x1235 
Table3: DWL 0x1234,0x1235 

DS

During the work with serial communication or writing data on LCD, it is often needed to use ASCII values instead of binary. Directive DS writes to program memory ASCII values of constant array of characters that are written inside the quotes. In the case of character “0”, in memory will be written character ASCII value 48.

Table4: DS “0123456789” 

When all elements of constant character array are loaded in memory, there is a need to somehow detect an end of array. Because of that it is common to add ASCII character NULL to an end of array, which is represented as binary 0.

Table5: DS “HelloWorld” DB 0 

INCLUDE

include "filename" Directive include is used to insert content of given .asm or .inc files. In this way it is possible to combine several files which contain different parts of program, thus improving code readability and reusability. There is a directive in the beginning of main program include “m8c.inc” which enables access to microcontrollers registers. File PSoCAPI.inc is used as a connection towards files that contain procedures for working with selected programmable blocks.

; Assembly main line 
include "m8c.inc" // 
include "memory.inc" // Constants & macros for SMM/LMM and Compiler 
include "PSoCAPI.inc" // PSoC API definitions for all User Modules 
include "User.inc" 
export _main 

_main: 
call PWM16_1_Start 
.terminate: jmp .terminate

EXPORT

 export procedure_name

Directive EXPORT is being used to mark that the procedure written in current file can be used in other files. Directive Export is put before procedure implementation, usually in the begging of that file. As an example is given file with procedures for programmable component PWM16.

EQU

equ value

Directive EQU enables giving constant name to some value Before compiling that name is automatically changed into according constant value.

4.6 Addressing modes

There are several ways to fetch data during instruction execution, which are all called under one name addressing methods Depending on whether data is a constant, RAM variable or register variable, there are immediate, direct, index and indirect addressing method. Beside these complicated looking names, very simple procedures are hidden.

Immediate addressing

When data is a constant value, then it is considered as immediate addressing. For example: Data could be RAM variable, or a register. Easiest way to access value of that variable is by putting it’s name inside of brackets. If we didn't put those brackets, we would access address of that variable, instead of its value.

Register addressing

When accessing register, beside brackets, it is also needed to put registered word reg, which shows that it is done in register address space.

Index addressing

One other thing that also happens very often is the need to access continuous memory locations. In that case we could some help from register X, which has a possibility of index addressing. Index register X is used to store address of some variable. Incrementing and decrementing values of the index register it is possible, in a simple way, to access elements of an array.

 

Using instruction MVI, it is no longer needed to continuously increment register X. In this case variable which plays role of a pointers used instead of register X. Its value is previously initialized to hold address of the variable that is being accessed. MVI transfers values between accumulator A and value of the variable, with initialization of pointer-variable so it stores address of next variable in array.

[back to the top]

Previouos chapter | Table of Contents | Next chapter →