A-level Computing 2009/AQA/Processing and Programming Techniques/Machine Operation and Assembly Language

From Wikibooks, open books for an open world
Jump to navigation Jump to search

Machine Code[edit | edit source]

Machine code is a binary programming language and is the form most easily processed by a CPU. Each line of code contains an operator (a binary representation of an instruction) and an operand (the data to be opererated on by the given instruction).

Assembly Language Instructions[edit | edit source]

Assembly language is an intermediate stage between machine code and high-level language and can usually be converted to machine code by a direct translation. Like machine code, an assembly language instruction contains an operator and one or more operands.

The exact range of instructions available to a processor will vary for each processor. However there are four different types of instructions available to any given processor:

Data Transfer Instructions[edit | edit source]

Data transfer instructions are used to move data between registers and between registers and main memory.

Arithmetic Instructions[edit | edit source]

Arithmetic instructions can be used to perform arithmetic functions on the contents of the registers. Some processors allow a range of arithmetic instructions such as addition, subtraction, multiplication, division and incrementation. Some others only allow addition and subtraction.

Logic Instructions[edit | edit source]

Logic instructions can be used to perform logic functions on the contents of the registers. Some examples of logic instructions are; and, or, xor and not. These can be useful when masking numbers, for instance converting from ASCII to binary representation of numbers or converting from higher to lower case ASCII.

AND[edit | edit source]

Only when there is the comparison of two 1s is the answer one.

OR[edit | edit source]

Only when there are one or more 1s in a comparison is the answer one.

XOR[edit | edit source]

or EOR (Exclusive OR / eXclusive OR)
Only when there is exactly one 1 in a comparison is the answer one.

NOT[edit | edit source]

Flip the 1s to 0s and the 0s to 1s. Useful for Two's Complement.

Masking[edit | edit source]

Example of conversion from ASCII to binary representation of a number: The ASCII representation of the denary number 3 is The binary representation is So to convert from ASCII to binary we need to mask out the first four bits of the binary representation and maintain the last four bits. There are several ways to do this.

AND solution

Note that we have set the last four bits to 1, try converting another ASCII number and see if this mask works for all of them?

XOR solution

Note that we only set the two bits different between the ASCII and binary to 1.  Try this mask for other ASCII numbers
Rules of Thumb
AND, if you want to keep a part of a number, AND 1 with it.  If you want to blank out part of a number, AND 0 with it.
OR, if you want to keep a part of a number, OR 0 with it.  If you want to set part of a number, OR 1 with it.
XOR, if you want to keep a part of a number, XOR 0 with it.  If you change a one to a zero XOR a 1 with it.

Dealing with don't care[edit | edit source]

The exam may ask you questions where you have to build a mask for a particular number, checking for ones and zeros as well as ignoring contents of certain cells. Below is a quick crib table (X = don't care about the input)

AND

If you place any other input into the equation other than the desired input the result will come out incorrect. You can now compare this with the number and if equal then you know the correct input was received.

OR

If you place any other input into the equation other than the desired input the result will come out incorrect. You can now compare this with the number and if equal then you know the correct input was received.

Example in assembly

You are allowed to input the following number only , write some assembly language to check that this works correctly.

AND 1 0 1
CMP 0 0 1
BEQ label

Try writing the OR version of the above code.

Shift Operations[edit | edit source]

If you look at the binary representations of the following numbers you will notice something peculiar:

0001 = 1
0010 = 2
0100 = 4
1000 = 8

Each time we shift the number one space to the left, the value of the number doubles. This doesn't only work for one bit, take a look at this more complicated example.

0001 0101 = 21
0010 1010 = 42

Again, one shift to the left and the number has doubled. On the other hand, one shift to the right halves the value.

Computers are notoriously bad at doing multiplication and division, it takes lots of CPU time and can really slow your code down. To try and get past this problem computers can shift the values in registers and as long as multiplication or division is by powers of 2, then the CPU time is reduced as the action takes only one line of Machine Code. There are three main types of shifts that processors can perform:

Logical Shift[edit | edit source]

Shifting either left or right, you add a 0 on the empty end.

Arithmetic Shift[edit | edit source]

You maintain the sign bit of the number being shifted. Generally only shifts right

Please note the Logical shift example is also an example of an arithmetic shift as the sign remains the same

Circular Shift[edit | edit source]

The bit that is pushed off one end appears on the other

Test and Branch Instructions[edit | edit source]

Test and branch instructions are used to test whether a given condition is true or not and then branch to a given instruction depending on the outcome of the test. This makes conditional statements and interation possible.

Computer Instructions[edit | edit source]

Computers understand instructions in things called words. In a computing context a word is the number of bits a computer can execute at one time. You will get processors that can understand different word sizes, for example the processor on the Sony PlayStation had a 32 bit word size. Sony decided to make the PlayStation 2 better than the original and the word size of the PlayStation 2 was 128 bits. Generally larger word sizes mean faster and more complex CPUs.

The word that a computer can understand is made up of two parts. The first is the type of instruction, or the opcode, the second part contains the variable(s) on which the instruction will execute, or the operand. The operand is sometimes called the address and the following section will explain how a computer can use the operand in different ways.

0 address instruction[edit | edit source]

This type of instruction takes no parameters and involves Assembly code that doesn't need variables. For example:

  • CLC - clear the carry flag
  • EXIT - exit a subroutine
  • INC - increment the accumulator by 1

1 address instruction[edit | edit source]

This type of instruction is very useful when you are dealing with only one general purpose register (the accumulator) and takes only one operand. For example

  • LDA #34 - load the accumulator with the denary value of 34
  • ADD 234 - add the value stored at memory location 234 to the accumulator

2 address instruction[edit | edit source]

This type of instruction can accept two operands and the complexity of operations increases. For example ADD R1, R2 - add R1 to R2 and store the result back into R1

Addressing Formats[edit | edit source]

There are different methods that a processor can use to calculate the memory address of the instruction being processed or the data being operated on. These are referred to as addressing modes.

Immediate Addressing[edit | edit source]

This is the addressing mode you have been used to using so far, where the data being operated on is given in the instruction.

Like this: LDA #35 ;Load the number 35 immediately into the accumulator.

Direct Addressing[edit | edit source]

In direct addressing the location of the data will be given in the instruction.

Like this: LDA 35 ;Load the contents of location 35 in to the accumulator.

Indirect Addressing[edit | edit source]

This is similar to direct address, although instead of the instruction giving the address of the data it gives an address where the address to the data is held. For example. If memory location A0 contained “F1” and memory location F1 contained “42” then to load 42 in to the accumulator the instruction would be:

LDA (&A0) ;Loads the contents of address given at &A0 in to acc

Relative Addressing[edit | edit source]

This type of addressing gives a memory location in terms of the current location in memory.

For example: JMP +10 ;branch to the instruction held 10 bytes on.

If this instruction was held at location 1 then it would jump to location 11.

Base Register Addressing[edit | edit source]

This type of addressing combines the specified with the address held in another location.

LDA &12,B ;loads acc with contents of the address formed by adding the contents of B with the hex address 12.

In this example the address &12 would be added to the address held in B to find the address of the data to be loaded in to the accumulator.

Indexed Addressing[edit | edit source]

This form of addressing is similar to base register addressing, except that the base addresses are held in an index register. If using this addressing format then the address of an operand can be changed by changing the contents of the index register.

LDA TABLE,X ;Load in to the ACC the contents of TABLE + x

A story to help you tell the difference[edit | edit source]

There was once a gangster called the Accumulator, pretty cool name huh? He had a lot of 'business' that he was involved in and had to be paid accordingly. He liked to be paid in several different ways. These were immediately, directly, indirectly, indexed and relative.

When he was paid immediately his goon would give him the money there and then, he got it without having to go find it or solve any clues, he got it immediately.

"Boss here's the £5" =
"LDA #5"

When he was paid directly he had to do a little bit of work, all across town he had lots of Post boxes that his clients would drop off payments in. He would be given the name of a particular post box and know that if he went there he would find the cash he wanted. He was directed to the cash.

"Boss the money is in the postbox at address 1023".
= "LDA 1023"

You must understand that the Accumulator had other business friends who were up to some dodgy business and preferred to remain as hidden as possible in their business dealings to keep the cops off their tracks. To do this they used a clever system of putting the money in a post box but instead of directly giving the Accumulator the address they instead gave the Accumulator the address of a postbox that contained the address of the real postbox. They gave him the address indirectly. Sounds a little confusing? Don't worry, hopefully this short transcript will sort things out

"Boss the address of where the money is, is in the postbox at 304"
The Accumulator opens the postbox at 304 and finds a note saying go to 706
When he gets to 706 he finds the money he was looking for
= "LDA (304)"

Business for a gangster is not always straight forward and occasionally they have to solve a clue or two to get their money, a bit like in the movies. In the case of an Indexed payment, Accumulator is given a clue to solve, he knows the base address and someone provides a value that must be added to the base value. He adds these two together and bingo he finds the address at which the money he is owed is stored.

"Boss the base address you need is 7987"
"Boss our sources say that the house your money is stored at is 5 houses up from the base address"
the Accumulator looks in 7987+5 (7992) and finds the cash he is looking for
= LDA TABLE,X

Assembly Code[edit | edit source]

Computers can understand only 1s and 0s. To get computers to understand what we want them to do we must get our ideas into these 1s and 0s. You can use High level languages or the low level language of Assembly. In Assembly code every line of code will generally transfer into one line of machine code. Assembly is used in industry to program low level routines and functions and the code produced is usually simple but long.

Instruction sets[edit | edit source]

An instruction set is the range of different instructions that a CPU can understand. There are two schools of thought, the RISC and the CISC. The RISC - reduced instruction set computer has a small number of different instructions it can perform but it generally does them very fast and efficiently. CISC - complex instruction set computer has a large number of different instructions it can perform but often not as fast as executing them as an equivalent RISC.

For the exam you need to know some basic Assembly instructions that a CPU can understand. We will now look at a range of instructions and then some examples of their use.

Basic instructions[edit | edit source]

ADD #34
add a number to the accumulator and store the value in the accumulator
SUB #34
take a number from the accumulator and store the value back in the accumulator
DEC
take one from the accumulator
INC
add one to the accumulator
LDA 34
load the accumulator with the value contained in memory location 34
STO 34
store the accumulator value into the memory location 34
CMP &34
compare the accumulator against the hexadecimal value of 34 and store the details in the status register
BNE label1
if the comparison was not equal then jump to label label1
BEQ label1
if the accumulator matched the value being compared the jump to label label1
BGT label1
if the accumulator is greater than the value compared jump to label label1
BLT label1
if the accumulator was less than the value compared jump to label label1
JMP label1
jump directly to label label1, similar to the goto function in some high level languages
AND 01001001
'AND' the accumulator with the value 01001001 storing the result in the accumulator
OR 01001001
'OR' the accumulator with the value 01001001 storing the result in the accumulator
XOR 01001001
'XOR' the accumulator with the value 01001001 storing the result in the accumulator
NOT
not the accumulator storing the result back in the accumulator
MOV R1, R2
Move the contents of register R1 into register R2

add shift instructions here

Labels[edit | edit source]

You may have noticed that several of the commands above call for the program to 'jump' to a label called label1. This performs the same function as the 'goto' statement in languages like C. Although the goto statement is frowned on in high level languages, it is essential in Assembly to execute loops and conditional statements. labels will appear like this in code:

LDA #40
label1:
INC
CMP #46
BLT label1
STO 1024

this piece of code loads the accumulator with the value 40. The accumulator is then increased by one and tested against the number 46. If the accumulator is less than 46 then you jump to the label1 to keep incrementing the accumulator. What value will be stored in memory location 1024?

Examples[edit | edit source]

In the examinations you will be often asked to take a piece of pseudo or real code and convert it into assembly. To make sure the examiner knows what you are doing always write comments with your code. Below are some examples of pseudo code along side their assembly equivalents

x = x + 1
LDA x
INC
STO x
while (x >= 6)
x = x + 1
y = y + 4
end while
while:
LDA x
CMP #6
BLT end
INC
STO x
LDA y
ADD #4
STO y
end:

Quick Check Questions[edit | edit source]

Provide assembly code that will complete the following tasks:

Q0[edit | edit source]

y = x + y

Q1[edit | edit source]

working out the negative two's complement of a given binary number x and storing it back in x

Q2[edit | edit source]

changing a ASCII lower case letter to its binary equivalent

Q3[edit | edit source]

do x= x-1
z++
while (z != 10)