Microelectronics: SOFTWARE -- Mnemonics



Home | Forum | DAQ Fundamentals | DAQ Hardware | DAQ Software

Input Devices
| Data Loggers + Recorders | Books | Links + Resources


AMAZON multi-meters discounts AMAZON oscilloscope discounts


Short assembler programs are used to demonstrate how a CPU performs elementary tasks. The mnemonics investigated are those for arithmetic and logical operations, data transfer, branching, and bit handling.

Whatever language is used for programming, the program used by the CPU consists of a series of opcodes and operands. In an assembler program, the opcodes are represented by mnemonics. These may be divided into a number of types, according to what they do. Below we will look more closely at a few of each type of mnemonic. They are demonstrated by using them in short assembler programs. These assembler programs are written for the '1200' microcontroller. Similar operations are available on all microprocessors and microcontrollers, though they may differ in the mnemonics used to identify them.

============

Architecture and programming

CPUs vary in the ways they handle data. Some do almost all the processing in a special register known as the accumulator. Some have a few additional registers, which assist the accumulator. Others, for example, the '1200' microcontroller, have no accumulator. Instead, it has 32 general-purpose registers, of which 16 can be used for arithmetical and logical operations.

The instruction set of a given CPU and the corresponding mnemonics of the assembler depend very much on whether processing is centered on the accumulator, or spread over several registers. Whatever the architecture, the general principles of processing in short simple steps is the same for all CPUs. The short programs in this SECTION are easily adaptable to a range of CPUs.

==============

Addition in stages

CPUs operate on pairs of numbers. They can add a and b to obtain their sum. If there are three numbers a, b, and c to be added, it has to be done in two stages:

a + b = sum1 sum1 + c = sum

There is an exception when two numbers and a carry bit are being added. All three are added in a single operation, as in the ADC operation, described on this page.

==============

Arithmetical mnemonics

These cover such operations as addition, subtraction, incrementing, decrementing, and clearing or setting registers. Addition and subtraction can only be done with two numbers. Adding two numbers in binary may produce a '1' to carry over to the next stage. This is stored as the carry digit (C) in the status (flag) register.

ADd with Carry (ADC) is used at the second and subsequent stages of a multi-stage addition. A short program to test this is:

;Demonstrating ADC, adding 149 + 47 + 1 (carry) sec ;set carry flag.

ldi r16, 149 ;load r16 with 149.

ldi r17, 47 ;load r17 with 47.

adc r16,r17 ;add all three and put the

;sum in r16.

To prepare the program for demonstrating ADC, the carry flag is set and the two numbers are loaded. The registers hold this:


After the final line of the program (ADC), the registers hold this:


The addition has not produced a carry (that is, there is no ninth bit) so C has been reset. Some other flags have been set, but these are not relevant to this calculation. Now r16 holds the sum (= 197), and r17 still holds the value with which it was loaded.

SUBtract without carry (SUB) ignores the state of C. A short program to test this is:

;Demonstrating SUB, subtracting 47 from 149.

ldi r16, 149 ;load r16 with 149.

ldi r17, 47 ;load r17 with 47.

sub r16,r17 ;subtract r17 from r16 and

;put the result in r16.

The carry flag may be '0' or '1', depending on the result of a previous operation. After the numbers have been loaded, the registers hold this:


After the final line of the program, the registers hold this:


No carry is produced so C has been reset. R16 now holds the difference (= 102), and r17 still holds the value with which it was loaded.

Logical mnemonics

Logical operations are bitwise (between corresponding pairs of bits), as these examples show. There are no carries with logic, so the C flag never gets set.

AND is demonstrated by a short program, using the same two values used in the operations above. After the values are loaded, the registers hold:


After the final line of the program, the registers hold this:


Only in the first and third columns from the right is there a '1' in r16 AND r17.

EOR (called XOR in some instruction sets) is the logical operation of exclusive-OR. The result is '1' if either of the two bits (but not both of the bits) are '1'.

Before operating on the same two values as before, we have:


The result of EOR is:


Data transfer

There are instructions for transferring (or copying, to be more correct) data from one register of the CPU to another. There are also instructions for sending output to a port, and for reading in data received by a port. With many CPUs, data can also be copied from a register to an address in RAM, or from an address in RAM to a register.

OUT copies data from a general-purpose register to a port register. A short program demonstrates the action of OUT:

; Demonstrating the action of OUT ldi r19, 255 ;all 1's out $17, r19 ;to ddrb ldi r20, 165 ;binary 10100101 out $18, r20 ;to portb register ldi r20, 0 ;binary 00000000 out $18, r20 ;to port b register

The first step is to configure all lines of Port B as outputs. This is done by using out to write 11111111 into data direction register B, which has the address $17 in the I/O memory space. Then the data from r20 is copied to the Port B register, which has the address $18. This could be checked by looking at the port register using simulator software, or by using a multimeter to measure the output voltage at each pin.

In the '1200', '0' means a logic high output, so D1, D3, D4 and D6 should be high, and the rest low. In the last two lines, out is used a second time to make all outputs high. You will need to single-step the program to give time to check outputs after the sixth line.

ST tells the CPU to STore data in one of the registers. ST is followed by the number of the register in which the data is to be stored.

However, unlike ADI, it does not immediately declare the register number. Instead, it gives the CPU the number of another register (r30, also known as register Z) which is holding the number. This is rather an indirect way of copying data so it is referred to as store indirect. The end result is the same as if we used MOV, but the indirect feature is useful in certain programs, as we shall show later.

A dry run helps explain the action of ST:


=======

Indirection

This is a technique that is often used in programs. Instead of giving the CPU a value directly, the CPU is told the number of a register where the value is already stored.

Example:

ldi r19, 48 is a direct or immediate command. It means 'load register 19 with the value that follows immediately (48)'. st X, r16 is an indirect command. It means 'look in register X (actually r30), find the register number that is stored there, and then store the contents of r16 in the register that has that number'. Register X acts as a pointer to another register.

Indirection makes programming more complicated but it has a useful feature. A direct address (the '48' in the example above) is written into the program. It cannot be altered while the program is running. With indirection, the number in X may be changed as the program runs. Then it may point to any of the other registers. In this way the value in r16 may be stored in different registers, depending on the stage the program has reached.

=======

The number of the destination register (r20) is placed in the Z register (r30). Then we put some data (125) in r16. ST tells the CPU to copy the data present in r16 into the register pointed at by Z.

Branch instructions

A branch instruction tells the CPU to stop working its way systematically along the program and to jump to some other part of the program instead. The jump may be forward or backward.

RJMP, or Relative JuMP, is the simplest of the branch instructions.

Normally the program counter is incremented after each fetch-execute cycle so that the CPU automatically fetches the next byte in the program for execution. RJMP puts a completely new address in the program counter, so the next fetch-execute cycle starts at a different place in the program.

The program below explores the action of RJMP in the forward direction:

; Demonstrating the relative jump, RJMP

ldi r16,10 rjmp land ldi r16,20 ldi r17,20 ldi r18,20 ldi r19,20 land: ldi r20,20 ldi r21,20 ldi r22,20

The CPU jumps to land on the third line up, so registers r20, r21 and r22 are loaded with '20'. Registers r16, r17, r18, and r19 are left unchanged.

Sometimes we want the CPU to continue working its way along the program provided that a given condition is true. However, if the condition is not true, we want it to branch to some other part of the program instead. This is known as a conditional branch or jump.

BREQ, or BRanch if EQual, makes the CPU jump to another point in the program if the result of a calculation is zero. Before making the jump, the CPU goes to the status register to find out if Z is set (= 1) or reset (= 0). The zero flag is set to 1 if the result of a previous operation is zero. If Z = 1, the CPU jumps to the branch address.

This program demonstrates the action of BREQ:

;Demonstrating BREQ ldi r16,5 repeat: dec r16 breq done rjmp repeat done: ldi r17,100 The program introduces another arithmetic opcode, DEC. This DECrements a register (reduces it) by 1. Here is the beginning of a dry run of this program. Column Z shows the zero flag, and PC is the program counter (program lines are numbered from 0):


The zero flag may be set or not to begin with, depending on the result of the previous calculation. Register r16 is loaded with '5' and the first decrementing results in '4'. The CPU runs round lines 1, 2 and 3 repeatedly, with r16 being decremented each time round. Eventually the CPU is sent back to repeat at line 1,with r16 holding 1 and with Z still zero:


This segment begins with the zero flag being set when R16 is eventually decremented to zero.

The routine ends with r16 = 0 and r17 = 100. The PC shows that the CPU has gone to line 4. The zero flag is still set because there have been no subsequent operations that involve it.

Bit and bit-test instructions

These are concerned with handling individual bits in a register, and setting or resetting some of the flags in the status register.

ROL is short for ROtate Left. Each bit in the register is shifted one place to the left. The operation involves the carry bit (C) of the status register. When the bits are shifted, the bit in carry is shifted into the register as the LSB. The MSB in the register is shifted into the carry bit.

Suppose that a register holds these bits:


The register holds 105, in binary. A left-shift puts 0 into the LSB and shifts 0 into the carry:


The register now holds 210. Shifting a binary number one place to the left is equivalent to multiplying it by 2. Left shifting is the basis for some multiplying routines. After a second left-shift we have:



The LSB holds 0 from the carry, but the carry now holds 1 from the previous MSB. Including the carry as a ninth bit, the value now equals 420. It has doubled again. A third shift gives:

The LSB holds 1 from the carry bit. The carry holds 1 from the previous MSB. There is no doubling this time because of the rotation.

The carry bit has gone into the LSB instead of being shifted along to give a tenth bit.

CLZ, or CLear Zero flag, changes the zero flag from 1 to 0, or leaves it as 0 if it is already 0. It is an example of several similar instructions for altering the carry flag (C), the negative flag (N), and others.

The programs above are intended simply to demonstrate some of the things that a CPU can do. Now we will look at ways in which these actions of the CPU can be used to do something useful. Before a system can process data, it must be able to accept data from the outside world. After it has processed the data, it needs to be able to pass it back to the outside world. The next SECTION describes routines for inputting and outputting data.

=======

A loop

The program demonstrating BREQ includes our first example of a loop. The CPU is made to repeat a section of the program. This is a conditional loop because the CPU is made to jump out of the loop when a certain condition becomes true. In this example, the condition is that r16 has been decremented to zero. The branch command tests the zero flag (Z) and makes the CPU jump out of the loop when Z = 1.

========

EXERCISE 1 -- Investigating mnemonics

The short programs in this SECTION are based on the instruction set of the '1200' microcontroller, using the Atmel AVR Assembler for Windows. It is likely that the reader will be using a different microcontroller or microprocessor and will be programming it with a different assembler, or directly in machine code, or in a high-level language such as C or Basic.

The programs in this guide are intended to illustrate the important features of processors in general and ways of programming. They show the reader how to tackle the programming of any processor using any programming system. The reader should not take these examples as something to be copied exactly. They are intended as models that the reader will adapt to a different processor and, in doing so, obtain a close understanding of their particular programming system.

==========

==========

1. If you are using an assembler, look through the list of mnemonics used by your assembler and find the mnemonics corresponding to those used in our examples.

Write short programs to demonstrate them. Use the examples given here as a guide.

2. If you are using machine code or a high-level language, write short programs, based on our examples, to demonstrate the corresponding actions of your processor.

3. Take each of the programs you have written in 1 or 2 above and rewrite it to do something a little different. For example, write programs to add two different numbers, to add three or four numbers (all less than 64), to subtract different numbers (including an example that produces a negative result). Instead of the assembler programs based on breq, experiment with the IF … THEN statement in BASIC, or the IF statement in C.

4. Investigate three more mnemonics, opcodes, or statements in the language you are using. Write short programs to demonstrate their action.

==================

Problems on: mnemonics

In some of these questions you are asked to write a short segment of a program. Base your answer on an assembler and processor with which you are familiar. Work out the program on paper, testing out your program with a dry run. When your answer is complete, test it by using an assembler program and a real or simulated processor.

1. Describe the action of two arithmetic mnemonics in an assembler program with which you are familiar.

2. Describe the addition of two values, 197 and 88 by a named CPU.

3. Show how a CPU calculates the bitwise AND of $B1 and $AB. What happens to the carry flag?

4. Outline the sequence of steps needed to output a byte of data at an 8-bit port. Write an assembler program to do this, based on an assembler and CPU of your choice.

5. The opposite of the BREQ mnemonic is BRNE (branch if not equal to zero). Write a short program to demonstrate its action.

6. Write an assembler program to multiply an integer number by 4. The maximum value that the number will have is 64.

7. Write an assembler program to multiply an integer number by 6. The maximum value that the number will have is 42. [Hint: This program involves both rotation and addition.]

8. Select two mnemonics other than those described in this SECTION and write an assembler program that uses them both. Add full comments to your program.

9. Rewrite any two of the assembler programs above, using BASIC or C. Discuss the differences between the assembler and the high-level language.

Answers to questions

PREV. | NEXT

Related Articles -- Top of Page -- Home

Updated: Thursday, May 18, 2017 10:11 PST