ARM AssyLang
ARM AssyLang
Contents
i vii ix 1
1 1 1 2 2 3 4 4 5 5 6 6 7 8 8 8 8 8 8
The Binary Programming Problem . . . . . . . . . . . . . . . . . . . . . . . . . . . Using Octal or Hexadecimal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Instruction Code Mnemonics 1.6.1 1.6.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The Assembler Program . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Additional Features of Assemblers Choosing an Assembler . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.7 1.8
Disadvantages of Assembly Language . . . . . . . . . . . . . . . . . . . . . . . . . . High-Level Languages 1.8.1 1.8.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Advantages of High-Level Languages . . . . . . . . . . . . . . . . . . . . . . Disadvantages of High-Level Languages
1.9
Which Level Should You Use? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.9.1 1.9.2 1.9.3 1.9.4 Applications for Machine Language . . . . . . . . . . . . . . . . . . . . . . . Applications for Assembly Language . . . . . . . . . . . . . . . . . . . . . . Applications for High-Level Language Other Considerations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2 Assemblers
2.1 Fields 2.1.1 2.1.2 2.2 2.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Delimiters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Labels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
11
11 11 12 14 14 14 15 16 17 17 17 18 18 18 18
The EQUATE Directive . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The AREA Directive . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Housekeeping Directives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . When to Use Labels Decimal Numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.4
Operands and Addresses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.4.1 2.4.2 2.4.3 2.4.4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Other Number Systems Character Codes
Names . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
ii
CONTENTS
2.4.5 2.4.6 2.5 2.6 2.7 2.8 Arithmetic and Logical Expressions General Recommendations . . . . . . . . . . . . . . . . . . . . . . 18 19 19 20 20 21
. . . . . . . . . . . . . . . . . . . . . . . . . . .
3 ARM Architecture
3.1 3.2 Processor modes 3.2.1 3.2.2 3.2.3 3.2.4 3.3 3.4 3.5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Registers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The stack pointer, The The
23
23 25 26 27 27 28 28 29 30 31 32 34
CPSR
. . . . . . . . . . . . . . . . . . .
Conditional Execution:
cc
. . . . . . . . . . . . . . . . . . . . . . . . . . .
op1 op2
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4 Instruction Set
4.0.4 4.0.5 4.0.6 4.0.7 4.0.8 4.0.9 Branch instructions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Data-processing instructions . . . . . . . . . . . . . . . . . . . . . . . . . . . Status register transfer instructions . . . . . . . . . . . . . . . . . . . . . . . Load and store instructions . . . . . . . . . . . . . . . . . . . . . . . . . . . Coprocessor instructions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exception-generating instructions . . . . . . . . . . . . . . . . . . . . . . . .
37
38 38 39 40 41 41 42
cc
. . . . . . . . . . . . . . . . . . . . . . . . . . .
5 Addressing Modes
5.1 Data Processing Operands: 5.1.1 5.1.2 5.1.3 5.1.4 5.1.5 5.1.6 5.2 5.2.1 5.2.2 5.2.3 Unmodied Value
op1
45
. . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 45 45 46 46 46 47 47 48 49 49
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Logical Shift Left . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Logical Shift Right . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Arithmetic Shift Right . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Rotate Right . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Rotate Right Extended
op2
6 Programs
6.1 Example Programs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.1.1 6.1.2 6.2 6.3 6.4 6.5 6.6 Program Listing Format . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Guidelines for Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
51
51 51 51 52 53 54 55 55 55
Trying the examples from the command line . . . . . . . . . . . . . . . . . . . . . . Setting up TextPad Program Initialization Special Conditions Problems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
CONTENTS
iii
7 Data Movement
7.1 Program Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.1.1 7.1.2 7.1.3 7.1.4 7.1.5 7.1.6 7.1.7 7.1.8 7.2 7.2.1 7.2.2 7.2.3 7.2.4 7.2.5 7.2.6 7.2.7 16-Bit Data Transfer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . One's Complement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32-Bit Addition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Shift Left One Bit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Byte Disassembly . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Find Larger of Two Numbers 64-Bit Adition Table of Factorials . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
57
57 57 58 59 60 61 62 63 64 65 65 65 65 66 66 66 66
Problems
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
64-Bit Data Transfer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32-Bit Subtraction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Shift Right Three Bits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Halfword Assembly . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Find Smallest of Three Numbers Shift Left . . . . . . . . . . . . . . . . . . . . . . . . Sum of Squares . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
bits
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
69 71
72 72 73 75 75 76 76 77 77 77 77
Problems
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Number of Zero, Positive, and Negative numbers . . . . . . . . . . . . . . . Find Minimum . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Count 1 Bits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Find element with most 1 bits
10 Strings
10.1 Handling data in ASCII 10.2 A string of characters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.2.1 Fixed Length Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.2.2 Terminated Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.2.3 Counted Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.3 International Characters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.4 Program Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.4.1 Length of a String of Characters 10.4.2 Find First Non-Blank Character . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
79
79 80 81 81 82 82 82 82 84 84 85 86 88 88 88 88 89 89
10.4.3 Replace Leading Zeros with Blanks . . . . . . . . . . . . . . . . . . . . . . . 10.4.4 Add Even Parity to ASCII Chatacters . . . . . . . . . . . . . . . . . . . . . 10.4.5 Pattern Match 10.5 Problems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
10.5.2 Find Last Non-Blank Character . . . . . . . . . . . . . . . . . . . . . . . . . 10.5.3 Truncate Decimal String to Integer Form 10.5.4 Check Even Parity and ASCII Characters . . . . . . . . . . . . . . . . . . . 10.5.5 String Comparison . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
iv
CONTENTS
11 Code Conversion
11.1 Program Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.1.1 Hexadecimal to ASCII . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.1.2 Decimal to Seven-Segment . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.1.3 ASCII to Decimal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.1.4 Binary-Coded Decimal to Binary . . . . . . . . . . . . . . . . . . . . . . . . 11.1.5 Binary Number to ASCII String 11.2 Problems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
91
91 91 92 93 94 95 96 96 96 96 97 97 97
11.2.1 ASCII to Hexadecimal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.2.2 Seven-Segment to Decimal . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.2.3 Decimal to ASCII . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.2.4 Binary to Binary-Coded-Decimal . . . . . . . . . . . . . . . . . . . . . . . . 11.2.5 Packed Binary-Coded-Decimal to Binary String . . . . . . . . . . . . . . . . 11.2.6 ASCII string to Binary number . . . . . . . . . . . . . . . . . . . . . . . . .
12 Arithmetic
12.1 Program Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.1.2 64-Bit Addition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.1.3 Decimal Addition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.1.4 Multiplication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.1.5 32-Bit Binary Divide . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.2 Problems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.2.1 Multiple precision Binary subtraction 12.2.3 32-Bit by 32-Bit Multiply
99
99 99 100 101 102 103 103 103 104
105
105 105 106 107 108 109 109 109 109 109 110 110
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
13.2.1 Remove Entry from List . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13.2.2 Add Entry to Ordered List 13.2.3 Add Element to Queue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13.2.4 4-Byte Sort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13.2.5 Using a Jump Table with a Key . . . . . . . . . . . . . . . . . . . . . . . .
111 113
113 114 114 114 115 115 116 116 123 123 123
CONTENTS
15.6.3 Test for Alphabetic Character . . . . . . . . . . . . . . . . . . . . . . . . . . 15.6.4 Scan to Next Non-alphabetic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15.6.5 Check Even Parity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15.6.6 Check the Checksum of a String 15.6.7 Compare Two Counted Strings
125 127
127 128 128 129 129 130 130 131 131 131 132 132 133 133 134 134 135 135 136 136
A.10 MOV: Move . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A.11 MVN: Move Negative A.12 ORR: Bitwise OR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
A.13 SBC: Subtract with Carry . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A.14 STM: Store Multiple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A.15 STR: Store Register A.17 SUB: Subtract . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A.16 STRB: Store Register Byte
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
A.18 SWI: Software Interrupt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A.19 SWP: Swap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A.20 SWPB: Swap Byte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
139
vi
CONTENTS
List of Programs
move16.s invert.s add.s add2.s shiftleft.s nibble.s bigger.s add64.s factorial.s bigger.s add64.s factorial.s sum16.s sum16b.s countneg.s countneg16.s largest16.s normalize.s strlencr.s skipblanks.s padzeros.s setparity.s
16bit data transfer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Find the one's compliment (inverse) of a number . . . . . . . . . . . . Add two numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Add two numbers and store the result . . . . . . . . . . . . . . . . . . Shift Left one bit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Disassemble a byte into its high and low order nibbles . . . . . . . . . Find the larger of two numbers . . . . . . . . . . . . . . . . . . . . . . 64 bit addition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Lookup the factorial from a table by using the address of the memory location . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
57 58 59 59 60 61 62 63 64 69 69 70 72 72 73 74 75 75 82 83 84 84 85 86
Find the larger of two numbers . . . . . . . . . . . . . . . . . . . . . . 64 bit addition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Lookup the factorial from a table by using the address of the memory location . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9.1a 9.1b 9.2a 9.2b 9.3 9.4 10.1a 10.2 10.3 10.4 10.5a
Add a series of 16 bit numbers by using a table address . . . . . . . . Add a series of 16 bit numbers by using a table address look-up Scan a series of 32 bit numbers to nd how many are negative Scan a series of 16 bit numbers to nd how many are negative Scan a series of 16 bit numbers to nd the largest . . . . . . . . . . .
. . . . . . . . . . .
Normalize a binary number . . . . . . . . . . . . . . . . . . . . . . . . Find the length of a Carage Return terminated string . . . . . . . . . Find the length of a null terminated string Supress leading zeros in a string . . . . . . . . . . . . . . . Find rst non-blank . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Set the parity bit on a series of characters store the amended string in Result . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Compare two counted strings for equality . . . . . . . . . . . . . . . . Compare null terminated strings for equality assume that we have no
10.1b strlen.s
nibtohex.s
. . . . . . . . . . .
91 92 92 93 94 94 95 99
Convert a 32 bit hexadecimal number to an ASCII string and output to the terminal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
nibtoseg.s Convert a decimal number to seven segment binary . . . . . . 11.3 dectonib.s Convert an ASCII numeric character to decimal . . . . . . . . 11.4a ubcdtohalf.s Convert an unpacked BCD number to binary . . . . . . . . . . 11.4b ubcdtohalf2.s Convert an unpacked BCD number to binary using MUL . . . 11.5 halftobin.s Store a 16bit binary number as an ASCII string of '0's and '1's
12.2
add64.s
64 Bit Addition
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
vii
viii
LIST OF PROGRAMS
Add two packed BCD numbers to give a packed BCD result . . . . . 100 101
12.3
16 bit binary multiplication . . . . . . . . . . . . . . . . . . . . . . . . Divide a 32 bit binary no by a 16 bit binary no store the quotient and remainder there is no 'DIV' instruction in ARM! . . . . . . . . . . . .
Multiply two 32 bit number to give a 64 bit result (corrupts R0 and R1)101 102
insert.s
Examine a table for a match - store a new entry at the end if no match found . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105 106 106 107 108 116 117 117 118 118 119 121 122 Examine a table for a match - store a new entry if no match found extends insert.s . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Examine an ordered table for a match . . . . . . . . . . . . . . . . . . Remove the rst element of a queue . . . . . . . . . . . . . . . . . . . Sort a list of values simple bubble sort . . . . . . . . . . . . . . . . . Initiate a simple stack . . . . . . . . . . . . . . . . . . . . . . . . . . . Initiate a simple stack . . . . . . . . . . . . . . . . . . . . . . . . . . . Initiate a simple stack . . . . . . . . . . . . . . . . . . . . . . . . . . . Initiate a simple stack . . . . . . . . . . . . . . . . . . . . . . . . . . . A simple subroutine example program passes a variable to the routine in a register . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A more complex subroutine example program passes variables to the routine using the stack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A 64 bit addition subroutine
15.1b init2.s
bystack.s
Preface
Broadly speaking, you can divide the history of computers into four periods: the mainframe, the mini, the microprocessor, and the modern post-microprocessor. The
mainframe
terized by computers that required large buildings and teams of technicians and operators to keep them going. More often than not, both academics and students had little direct contact with the mainframeyou handed a deck of punched cards to an operator and waited for the output to appear hours later. During the mainfame era, academics concentrated on languages and compilers, algorithms, and operating systems. The
minicomputer
era put computers in the hands of students and academics, because university As minicomputers were not as complex as main-
frames and because students could get direct hands-on experience, many departments of computer science and electronic engineering taught students how to program in the native language of the computerassembly language. In those days, the mid 1970s, assembly language programming was used to teach both the control of I/O devices, and the writing of programs (i.e., assembly language was taught rather like high level languages). The explosion of computer software had not taken place, and if you wanted software you had to write it yourself. The late 1970s saw the introduction of the
microprocessor.
able to access a real computer. Unfortunately, microprocessors appeared before the introduction of low-cost memory (both primary and secondary). capacity to hold a simple single-pass assembler. The advent of the low-cost microprocessor system (usually on a single board) ensured that virtually every student took a course on assembly language. Even today, most courses in computer science include a module on computer architecture and organization, and teaching students to write programs in assembly language forces them to understand the computer's architecture. However, some computer scientists who had been educated during the mainframe era were unhappy with the microprocessor, because they felt that the 8-bit microprocessor was a retrograde stepits architecture was far more primitive than the mainframes they had studied in the 1960s. The 1990s is the Students had to program microprocessors in assembly language because the only storage mechanism was often a ROM with just enough
post-microprocessor
era.
Today's personal computers have more power and Moreover, the computer science curriculum of the
storage capacity than many of yesterday's mainframes, and they have a range of powerful software tools that were undreamed of in the 1970s. 1990s has exploded. In 1970 a student could be expected to be familiar with all eld of computer science. Today, a student can be expected only to browse through the highlights. The availability of high-performance hardware and the drive to include more and more new material in the curriculum, has put pressure on academics to justify what they teach. In particular, many are questioning the need for courses on assembly language. If you regard computer science as being primarily concerned with the
use
can argue that assembly language is an irrelevance. Does the surgeon study metallurgy in order to understand how a scalpel operates? Does the pilot study thermodynamics to understand how a jet engine operates? Does the news reader study electronics to understand how the camera
ix
PREFACE
operates? The answer to all these questions is no . So why should we inict assembly language and computer architecture on the student? First,
education
training.
The student of computer science is not simply being A university course leading to a degree should for the subject. Without a knowledge of computer
history
theoretical basis
architecture, the computer scientist cannot understand how computers have developed and what they are capable of.
abstract
concepts in
subjects ranging from programming languages, to operating systems, to real-time programming, to AI. The foundation of many of these concepts lies in assembly language programming and computer architecture. You might even say that assembly language provides for the
top-down
bottom-up
support
examples (taken from the teaching of Advanced RISC Machines Ltd (ARM) assembly language).
Data types
Students come across data types in high-level languages and the eects of strong and weak data typing. Teaching an assembly language that can operate on bit, byte, word and long word operands helps students understand data types. Moreover, the ability to perform any type of assembly language operation on any type of data structure demonstrates the need for strong typing.
Addressing modes
A vital component of assembly language teaching is addressing modes (literal, direct, and indirect). The student learns how pointers function and how pointers are manipulated. This aspect is particularly important if the student is to become a C programmer. Because an assembly language is unencumbered by data types, the students' view of pointers is much simplied by an assembly language. The ARM has complex addressing modes that support direct and indirect addressing, generated jump tables and handling of unknown memory osets.
PREFACE
xi
reference.
The use of
local variables
and
re-entrant
value
and by
supports the teaching of task switching kernels in both operating systems and real-time programming.
Recursion
The recursive calling of subroutines often causes a student problems. You can use an assembly language, together with a suitable system with a tracing facility, to demonstrate how recursion operates. The student can actually observe how the stack grows as procedures are called.
Protected-mode operation
Members of the ARM family operate in either a
or a
user mode.
The
operating system operates in the priviledge mode and all user (applications) programs run in the user mode. This mechanism can be used to construct system (or other applications).
protected
environments in
which the eects of an error in one application can be prevented from harming the operating
Input-output
Many high-level languages make it dicult to access I/O ports and devices directly. By using an assembly language we can teach students how to write device drivers and how to control interfaces. Most real interfaces are still programmed at the machine level by accessing registers within them.
All these topics can, of course, be taught in the appropriate courses (e.g., high-level languages, operating systems). However, by teaching them in an assembly language course, they pave the way for future studies, and also show the student exactly what is happening within the machine.
Conclusion
A strong case can be made for the continued teaching of assembly language within the computer science curriculum. However, an assembly language cannot be taught just as if it were another general-purpose programming language as it was once taught ten years ago. Perhaps more than any other component of the computer science curriculum, teaching an assembly language supports a wide range of topics at the heart of computer science. An assembly language should not be used just to illustrate algorithms, but to demonstrate what is actually happening inside the computer.
xii
PREFACE
Introduction
A computer program is ultimately a series of numbers and therefore has very little meaning to a human being. In this chapter we will discuss the levels of human-like language in which a computer program may be expressed. We will also discuss the reasons for and uses of assembly language.
1.1
The instruction set of a microprocessor is the set of binary inputs that produce dened actions during an instruction cycle. An instruction set is to a microprocessor what a function table is to a logic device such as a gate, adder, or shift register. Of course, the actions that the microprocessor performs in response to its instruction inputs are far more complex than the actions that logic devices perform in response to their inputs.
111000000100
11100000010011101100000000001111
Subtract
111000001000
means:
The microprocessor (like any other computer) only recognises binary patterns as instructions or data; it does not recognise characters or octal, decimal, or hexadecimal numbers.
1.2
A Computer Program
A program is a series of instructions that causes a computer to perform a particular task. Actually, a computer program includes more than instructions, it also contains the data and the memory addresses that the microprocessor needs to accomplish the tasks dened by the instructions. Clearly, if the microprocessor is to perform an addition, it must have two numbers to add and a place to put the result. The computer program must determine the sources of the data and the destination of the result as well as the operation to be performed. All microprocessors execute instructions sequentially unless an instruction changes the order of execution or halts the processor. That is, the processor gets its next instruction from the next higher memory address unless the current instruction specically directs it to do otherwise. Ultimately, every program is a set of binary numbers. For example, this is a snippet of an ARM program that adds the contents of memory locations memory location
809432
and
809832
809C32 :
1
CHAPTER 1.
INTRODUCTION
1.3
There are many diculties associated with creating programs as object, or binary machine language, programs. These are some of the problems:
particularly after you have looked at them for a few hours.) The programs do not describe the task which you want the computer to perform in anything resembling a human-readable format. The programs are long and tiresome to write. The programmer often makes careless errors that are very dicult to locate and correct.
For example, the following version of the addition object program contains a single bit error. Try to nd it:
membering some of the binary codes, but such eort should be spent more productively.
1.4
We can improve the situation somewhat by writing instructions using octal or hexadecimal numbers, rather than binary. We will use hexadecimal numbers because they are shorter, and because they are the standard for the microprocessor industry. Table 1.1 denes the hexadecimal digits and their binary equivalents. The ARM program to add two numbers now becomes:
1.5.
Hexadecimal Digit 0 1 2 3 4 5 6 7 8 9 A B C D E F
Binary Equivalent 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111
Decimal Equivalent 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
1.5
An obvious programming improvement is to assign a name to each instruction code. The instruction code name is called a mnemonic or memory jogger.
In fact, all microprocessor manufacturers provide a set of mnemonics for the microprocessor instruction set (they cannot remember hexadecimal codes either). You do not have to abide by the manufacturer's mnemonics; there is nothing sacred about them. However, they are standard for a given microprocessor, and therefore understood by all users. These are the instruction codes Some instructions do for subtraction, that you will nd in manuals, cards, books, articles, and programs. The problem with selecting instruction mnemonics is that not all instructions have obvious names. (for example, and even
SUB
for exclusive-OR), while still others have neither. The result is such mnemonics as However, users who devise their own mnemonics rarely do much better.
MRS. Most manufacturers come up with some reasonable names and some hopeless ones.
Along with the instruction mnemonics, the manufacturer will usually assign names to the CPU registers. As with the instruction names, some register names are obvious (such as suggestions simply to promote standardisation. If we use standard ARM instruction and register mnemonics, as dened by Advanced RISC Machines, our ARM addition program becomes:
A for Accumu-
lator) while others may have only historical signicance. Again, we will use the manufacturer's
CHAPTER 1.
INTRODUCTION
The program is still far from obvious, but at least some parts are comprehensible. considerable improvement over
ADD is a E59F. The LDR mnemonic does suggest loading data into a register
or memory location. We now see that some parts of the program are operations and others are addresses. Such a program is an assembly language program.
1.6
How do we get the assembly language program into the computer? We have to translate it, either into hexadecimal or into binary numbers. You can translate an assembly language program by hand, instruction by instruction. This is called hand assembly. The following table illustrates the hand assembly of the addition program:
Instruction Mnemonic
Register/Memory Location
Hexadecimal Equivalent
Hand assembly is a rote task which is uninteresting, repetitive, and subject to numerous minor errors. Picking the wrong line, transposing digits, omitting instructions, and misreading the codes are only a few of the mistakes that you may make. Most microprocessors complicate the task even further by having instructions with dierent lengths. Some instructions are one word long while others may be two or three. Some instructions require data in the second and third words; others require memory addresses, register numbers, or who knows what? Assembly is a rote task that we can assign to the microcomputer. each instruction requires. The microcomputer never The assembler
makes any mistakes when translating codes; it always knows how many words and what format The program that does this job is an assembler. program translates a user program, or source program written with mnemonics, into a machine language program, or object program, which the microcomputer can execute. The assembler's input is a source program and its output is an object program. Assemblers have their own rules that you must learn. These include the use of certain markers (such as spaces, commas, semicolons, or colons) in appropriate places, correct spelling, the proper control of information, and perhaps even the correct placement of names and numbers. rules are usually simple and can be learned quickly. These
Allowing the user to assign names to memory locations, input and output devices, and even sequences of instructions Converting data or addresses from various number systems (for example, decimal or hexadecimal) to binary and converting characters into their ASCII or EBCDIC binary codes
1.7.
Telling the loader program where in memory parts of the program or data should be placed Allowing the user to assign areas of memory as temporary data storage and to place xed data in areas of program memory Providing the information required to include standard programs from program libraries, or programs written at some other time, in the current program Allowing the user to control the format of the program listing and the input and output devices employed
1.7
The assembler does not solve all the problems of programming. One problem is the tremendous gap between the microcomputer instruction set and the tasks which the microcomputer is to perform. Computer instructions tend to do things like add the contents of two registers, shift the contents of the Accumulator one bit, or place a new value in the Program Counter. On the other hand, a user generally wants a microcomputer to do something like print a number, look for and react to a particular command from a teletypewriter, or activate a relay at the proper time. An assembly language programmer must translate such tasks into a sequence of simple computer instructions. The translation can be a dicult, time-consuming job. Furthermore, if you are programming in assembly language, you must have detailed knowledge of the particular microcomputer that you are using. You must know what registers and instructions the microcomputers has, precisely how the instructions aect the various registers, what addressing methods the computer uses, and a mass of other information. None of this information is relevant to the task which the microcomputer must ultimately perform. In addition, assembly language programs are not portable. Each microcomputer has its own
assembly language which reects its own architecture. An assembly language program written for the ARM will not run on a 486, Pentium, or Z8000 microprocessor. For example, the addition program written for the Z8000 would be:
LD ADD LD
The lack of portability not only means that you will not be able to use your assembly language program on a dierent microcomputer, but also that you will not be able to use any programs that were not specically written for the microcomputer you are using. This is a particular drawback for new microcomputers, since few assembly language programs exist for them. The result, too frequently, is that you are on your own. If you need a program to perform a particular task, you are not likely to nd it in the small program libraries that most manufacturers provide. Nor are you likely to nd it in an archive, journal article, or someone's old program File. You will probably have to write it yourself.
CHAPTER 1.
INTRODUCTION
1.8
High-Level Languages
high-level procedure-oriented
The solution to many of the diculties associated with assembly language programs is to use, insted, or langauges. Such languages allow you to describe tasks in forms that are problem-oriented rather than computer-oriented. Each statement in a high-level language performs a recognisable function; it will generally correspond to many assembly language instruction. A program called a compiler translates the high-level language source program into object code or machine language instructions. Many dierent hgih-level languages exist for dierent types of tasks. (For mula If, for exampe, you can
express what you want the computer to do in algebraic notation, you can write your
Tran slation
FORTRAN
Language), the oldest of the high-level languages. Now, if you want to add
COBOL (for business BASIC (a cut down version of FORTRAN designed to prototype ideas before codeing full), C (a systems-programming language), C++ and JAVA (object-orientated general
development languages).
FORTRAN,
you could probably tell what the statement illustrated above does.
Machine Independence
High-level languages solve many other problems associated with assembly language programming. The high-level language has its own syntax (usually dened by an international standard). The language does not mention the instruction set, registers, or other features of a particular computer. The compiler takes care of all such details. Programmers can concentrate on their own tasks; they do not need a detailed understanding of the underlying CPU architecture for that matter, they do not need to know anything about the computer the are programming.
Portability
Programs written in a high-level language are portable at least, in theory. They will run on any computer that has a standard compiler for that language. At the same time, all previous programs written in a high-level language for prior computers and available to you when programming a new computer. This can mean thousands of programs in the case of a common language like
C.
1.8.
HIGH-LEVEL LANGUAGES
Syntax
One obvious problem is that, as with assembly language, you have to learn the rules or
syntax
of any high-level language you want to use. A high-level langauge has a fairly complicated set of rules. You will nd that it takes a lot of time just to get a program that is syntactically correct (and even then it probably will not do what you want). A high-level computer language is like a foreign language. If you have talent, you will get used to the rules and be able to turn out programs that the compiler will accept. Still, learning the rules and trying to get the program accepted by the compiler does not contribute directly to doing your job.
Cost of Compilers
Another obvious problem is that you need a compiler to translate program written in a high-level language into machine language. amounts of memory. Compilers are expensive and use a large amount of memory. While most assemblers occupy only a few KBytes of memory, compilers would occupy far larger A compiler could easily require over four times as much memory as an assembler. So the amount of overhead involved in using the compiler is rather large.
FORTRAN
Each
is well-suited to problems
terminal, editing a string of characters, or monitoring an alarm system, your problem cannot be easily expressed. In fact, formulating the solution in suitable high-level language. less widely used.
FORTRAN
more dicult than formulating it in assembly language. The answer is, of course, to use a more Languages specically designed for tasks such as those mentioned above do exist they are called system implementation languages. However, these languages are
Ineciency
High-level languages do not produce very ecient machine language program. The basic reason for this is that compilation is an automatic process which is riddled with compromises to allow for many ranges of possibilities. The compiler works much like a computerised language translator sometimes the words are right but the sentence structures are awkward. A simpler compiler connot know when a variable is no longer being used and can be discarded, when a register should be used rather than a memory location, or when variables have simple relationships. The experienced programmer can take advantage of shortcuts to shorten execution time or reduce memory usage. A few compiler (known as optimizing cmpilers) can also do this, but such compilers are much larger than regular compilers.
CHAPTER 1.
INTRODUCTION
1.9
Which language level you use depends on your particulr application. Let us briey note some of the factors which may favor particular levels:
Short to moderate-sized programs Application where memory cost is a factor Applications involving more input/output or control than computation
Low-volume applications
Availability of a specic program in a high-level language which can be used in the application.
1.10
Given the advance of high-level languages, why do you need to learn assembly language programming? The reasons are:
1.10.
1. Most industrial microcomputer users program in assembly language. 2. Many microcomputer users will continue to program in assembly language since they need the detailed control that it provides. 3. No suitable high-level language has yet become widely available or standardised. 4. Many application require the eciency of assembly language. 5. An understanding of assembly language can help in evaluating high-level languages. 6. Almost all microcomputer programmers ultimately nd that they need some knowledge of assembly language, most often to debug programs, write I/O routines, speed up or shorten critical sections of programs written in high-level languages, utilize or modify operating system functions, and undertand other people's programs.
The rest of these notes will deal exclusively with assembler and assembly language programming.
10
CHAPTER 1.
INTRODUCTION
Assemblers
This chapter discusses the functions performed by assemblers, beginning with features common to most assemblers and proceeding through more elaborate capabilities such as macros and conditional assembly. You may wish to skim this chapter for the present and return to it when you feel more comfortable with the material. As we mentioned, today's assemblers do much more than translate assembly language mnemonics into binary codes. But we will describe how an assembler handles the translation of mnemonics before describing additional assembler features. Finally we will explain how assemblers are used.
2.1
Fields
Assembly language instructions (or statements) are divided into a number of elds . The operation code eld is the only eld which can never he empty; it always contains either an instruction mnemonic or a directive to the assembler, sometimes called a pseudo-instruction, pseudo-operation, or pseudo-op. The operand or address eld may contain an address or data, or it may be blank. The comment and label elds are optional. A programmer will assign a label to a statement or add a comment as a personal convenience: namely, to make the program easier to read and use. Of course, the assembler must have some way of telling where one eld ends and another begins. Assemblers often require that each eld start in a specic column. This is a xed format. However, xed formats are inconvenient when the input medium is paper tape; xed formats are also a nuisance to programmers. The alternative is a free format where the elds may appear anywhere on the line.
2.1.1 Delimiters
If the assembler cannot use the position on the line to tell the elds apart, it must use something else. Most assemblers use a special symbol or delimiter at the beginning or end of each eld.
Label Field
VALUE1 VALUE2 RESULT START NEXT:
Comment Field
;FIRST VALUE ;SECOND VALUE ;16-BIT STORAGE FOR ADDITION RESULT ;GET FIRST VALUE ;ADD SECOND VALUE TO FIRST VALUE ;STORE RESULT OF ADDITION ;NEXT INSTRUCTION
11
12
CHAPTER 2.
label
ASSEMBLERS
whitespace
instruction
whitespace
; comment
Between label and operation code, between operation code and address, and before an entry in the comment eld Between operands in the address eld Before an entire line of comment Marks the start of a comment on a line that contains preceding code
Table 2.1: Standard ARM Assembler Delimiters
The most common delimiter is the space character. Commas, periods, semicolons, colons, slashes, question marks, and other characters that would not otherwise be used in assembly language programs also may serve as delimiters. The general form of layout for the ARM assembler is: You will have to exercise a little care with delimiters. Some assemblers are fussy about extra spaces or the appearance of delimiters in comments or labels. A well-written assembler will handle these minor problems, but many assemblers are not well-written. Our recommendation is simple: avoid potential problems if you can. The following rules will help:
Do not use extra spaces, in particular, do not put spaces after commas that separate operands, even though the ARM assembler allows you to do this. Do not use delimiter characters in names or labels. Include standard delimiters even if your assembler does not require them. Then it will be more likely that your programs are in correct form for another assembler.
2.1.2 Labels
The label eld is the rst eld in an assembly language instruction; it may be blank. If a label is present, the assembler denes the label as equivalent to the address into which the rst byte of the object code generated for that instruction will be loaded. You may subsequently use the label as an address or as data in another instruction's address eld. The assembler will replace the label with the assigned value when creating an object program. The ARM assembler requires labels to start at the rst character of a line. However, some other assemblers also allow you to have the label start anywhere along a line, in which case you must ARM assembler. Labels are most frequently used in Branch or SWI instructions. These instructions place a new value in the program counter and so alter the normal sequential execution of instructions. means place use a colon (:) as the delimiter to terminate the label eld. Colon delimiters are not used by the
B 15016 the value 15016 in the program counter. The next instruction to be executed will be the one in memory location 15016 . The instruction B START means place the value assigned to the label START in the program counter. The next instruction to be executed will be the on at the address corresponding to the label START. Figure 2.1 contains an example.
Why use a label? Here are some reasons:
A label makes a program location easier to nd and remember. The label can easily be moved, if required, to change or correct a program. The assembler will automatically change all instructions that use the label when the program is reassembled.
2.1.
FIELDS
13
When the machine language version of this program is executed, the instruction B START causes the address of the instruction labeled START to be placed in the program counter That instruction will then be executed.
Figure 2.1: Assigning and Using a Label
The assembler can relocate the whole program by adding a constant (a relocation constant) to each address in which a label was used. Thus we can move the program to allow for the insertion of other programs or simply to rearrange memory.
The program is easier to use as a library program; that is, it is easier for someone else to take your program and add it to some totally dierent program. You do not have to gure out memory addresses. Figuring out memory addresses is particularly dicult with microprocessors which have instructions that vary in length.
You should assign a label to any instruction that you might want to refer to later. The next question is how to choose a label. The assembler often places some restrictions on the number of characters (usually 5 or 6), the leading character (often must be a letter), and the trailing characters (often must be letters, numbers, or one of a few special characters). Beyond these restrictions, the choice is up to you. Our own preference is to use labels that suggest their purpose, i.e., mnemonic labels. examples are Typical
ADDW in a routine that adds one word into a sum, SRCHETX in a routine that searches for the ASCII character ETX, or NKEYS for a location in data memory that contains the number of
key entries. Meaningful labels are easier to remember and contribute to program documentation. Some programmers use a standard format for labels, such as starting with the program. Some label selection rules will keep you out of trouble. We recommend the following:
L0000.
self-sequencing (you can skip a few numbers to permit insertions), but they do not help document
Do not use labels that are the same as operation codes or other mnemonics. Most assemblers will not allow this usage; others will, but it is confusing. Do not use labels that are longer than the assembler recognises. Assemblers have various rules, and often ignore some of the characters at the end of a long label. Avoid special characters (non-alphabetic and non-numeric) and lower-case letters. stick to capital letters and numbers. Some
assemblers will not permit them; others allow only certain ones. The simplest practice is to
Start each label with a letter. Such labels are always acceptable. Do not use labels that could be confused with each other. Avoid the letters the numbers
0, 1,
and
2.
XXXX
and
XXXXX.
I, O,
and
and
Assembly programming is
When you are not sure if a label is legal, do not use it. You will not get any real benet from discovering exactly what the assembler will accept.
14
CHAPTER 2.
ASSEMBLERS
These are recommendations, not rules. You do not have to follow them but don't blame us if you waste time on unnecessary problems.
2.2
One main task of the assembler is the translation of mnemonic operation codes into their binary equivalents. The assembler performs this task using a xed table much as you would if you were doing the assembly by hand. The assembler must, however, do more than just translate the operation codes. It must also
somehow determine how many operands the instruction requires and what type they are. This may be rather complex some instructions (like a Stop) have no operands, others (like a Jump instruction) have one, while still others (like a transfer between registers or a multiple-bit shift) require two. Some instructions may even allow alternatives; for example, some computers have instructions (like Shift or Clear) which can either apply to a register in the CPU or to a memory location. We will not discuss how the assembler makes these distinctions; we will just note that it must do so.
2.3
Directives
Some assembly language instructions are not directly translated into machine language instructions. These instructions are directives to the assembler; they assign the program to certain areas in memory, dene symbols, designate areas of memory for data storage, place tables or other xed data in memory, allow references to other programs, and perform minor housekeeping functions. To use these assembler directives or pseudo-operations a programmer places the directive's mnemonic in the operation code eld, and, if the specied directive requires it, an address or data in the address eld. The most common directives are:
Dierent assemblers use dierent names for those operations but their functions are the same. Housekeeping directives include:
END
LIST
FORMAT
TTL
PAGE
INCLUDE
We will discuss these pseudo-operations briey, although their functions are usually obvious.
2.3.
DIRECTIVES
15
Names Messages Commands Tax tables Thresholds Test patterns Lookup tables Standard forms Masking patterns Weighting factors
Conversion factors Key identications Subroutine addresses Code conversion tables Identication patterns State transition tables Synchronisation patterns Coecients for equations Character generation patterns Characteristic times or frequencies
The dene constant directive treats the data as a permanent part of the program. The format of a dene constant directive is usually quite simple. An instruction like:
DZCON DZCON. DC
DCW
12
will place the number 12 in the next available memory location and assign that location the name Every directive usually has a label, unless it is one of a series. The data and label may take any form that the assembler permits. More elaborate dene constant directives that handle a large amount of data at one time are provided, for example:
EMESS SQRS
DCB DCW
'ERROR' 1,4,9,16,25
A single directive may ll many bytes of program memory, limited perhaps by the length of a line or by the restrictions of a particular assembler. Of course, you can always overcome any restrictions by following one dene constant directive with another:
MESSG
"NOW IS THE " "TIME FOR ALL " "GOOD MEN " "TO COME TO THE " "AID OF THEIR " "COUNTRY", 0 ;note the '0' terminating the string
Microprocessor assemblers typically have some variations of standard dene constant directives. Dene Byte or to (Dene Other special directives may handle character-coded data. The ARM assembler also denes
DCB handles 8-bit numbers; Dene Word or DCW handles 32-bit numbers or addresses. DCD Constant Data) which may be used in place of DCW.
EQU.
This
dresses, numeric data, starting addresses, xed addresses, etc. The EQUATE directive assigns the numeric value in its operand eld to the label in its label eld. Here are two examples:
TTY LAST
EQU EQU
5 5000
16
CHAPTER 2.
ASSEMBLERS
Most assemblers will allow you to dene one label in terms of another, for example:
LAST ST1
EQU EQU
FINAL START+1
The label in the operand eld must, of course, have been previously dened. Often, the operand eld may contain more complex expressions, as we shall see later. Double name assignments (two names for the same data or address) may be useful in patching together programs that use dierent names for the same variable (or dierent spellings of what was supposed to be the same name). Note that an EQU directive does not cause the assembler to place anything in memory. The assembler simply enters an additional name into a table (called a symbol table) which the assembler maintains. When do you use a name? The answer is: whenever you have a parameter that you might want to change or that has some meaning besides its ordinary numeric value. We typically assign names to time constants, device addresses, masking patterns, conversion factors, and the like. A name like
DELAY, TTY, KBD, KROW, or OPEN not only makes the parameter easier to change, but it also adds to
program documentation. We also assign names to memory locations that have special purposes; they may hold data, mark the start of the program, or be available for intermediate storage. What name do you use? The best rules are much the same as in the case of labels, except that here meaningful names really count. Why not call the teletypewriter time delay rather
TTY instead of X15, a bit BTIME or BTDLY rather than WW, the number of the GO key on a keyboard GOKEY than HORSE? This advice seems straightforward, but a surprising number of programmers
do not follow it. Where do you place the EQUATE directives? The best place is at the start of the program, under appropriate comment headings such as or
program locations.
This makes the denitions easy to nd if you want to change them.
Furthermore, another user will be able to look up all the denitions in one centralised place. Clearly this practice improves documentation and makes the program easier to use. Denitions used only in a specic subroutine should appear at the start of the subroutine.
AREA
Reset (startup) address Interrupt service addresses Trap (software interrupt) addresses RAM storage
2.4.
17
Still other origin statements may allow room for later insertions, place tables or data in memory, or assign vacant memory space for data buers. Program and data memory in microcomputers may occupy widely separate addresses to simplify the hardware. Typical origin statements are:
The assembler will assume a fake address if the programmer does not put in an assembly to fail.
The AREA statement at the start of an ARM program is required, and its absence will cause the
END,
marks the end of the assembly language source program. This must appear in the le or a missing END directive error will occur.
INCLUDE
will include the contents of a named le into the current le. When the included le
has been processed the assembler will continue with the next line in the original le. For example the following line
INCLUDE
MATH.S
math.s
You should never use a lable with an include directive. Any labels dened in the included le will be dened in the current le, hence an error will be reported if the same label appears in both the source and include le. An include le may itself include other les, which in turn could include other les, and so on, however, the level of includes the assembler will accept is limited. It is not recommended you go beyond three levels for even the most complex of software.
EQU
directives must have labels; they are useless otherwise, since the purpose of an
EQU
is to dene its label. 2. Dene Constant and Dene Storage directives usually have labels. The label identies the rst memory location used or assigned. 3. Other directives should not have labels.
2.4
The assembler allow the programmer a lot of freedom in describing the contents of the operand or address eld. But remember that the assembler has built-in names for registers and instructions and may have other built-in names. We will now describe some common options for the operand eld.
18
CHAPTER 2.
ASSEMBLERS
ADD
100
means add the contents of memory location 100 10 to the contents of the Accumulator.
8_nnn
nnn 0xnnn
It is good practice to enter numbers in the base in which their meaning is the clearest: that is, decimal constants in decimal; addresses and BCD numbers in hexadecimal; masking patterns or bit outputs in hexadecimal.
2.4.3 Names
Names can appear in the operand eld; they will be treated as the data that they represent. Remember, however, that there is a dierence between operands and addresses. assembly language program the sequence: In an ARM
FIVE
5 R2, #FIVE
will add the contents of memory location FIVE (not necessarily the number 5) to the contents of data register
START+1.
division, logical functions, shifts, etc. Note that the assembler evaluates expressions at assembly time; if a symbol appears in an expression, the address is used (i.e., the location counter or EQUATE value). Assemblers vary in what expressions they accept and how they interpret them. Complex expressions make a program dicult to read and understand.
2.5.
COMMENTS
19
Use the clearest number system or character code for data. Masks and BCD numbers in decimal, ASCII characters in octal, or ordinary numerical constants in hexadecimal serve no purpose and therefore should not be used. Remember to distinguish data from addresses. Don't use osets from the location counter. Keep expressions simple and obvious. Don't rely on obscure features of the assembler.
2.5
Comments
All assemblers allow you to place comments in a source program. Comments have no eect on the object code, but they help you to read, understand, and document the program. Good commenting is an essential part of writing computer programs, programs without comments are very dicult to understand. We will discuss commenting along with documentation in a later chapter, but here are some guidelines:
Use comments to tell what application task the program is performing, not how the microcomputer executes the instructions. Comments should say things like is temperature above limit?, linefeed to TTY, or examine load switch. Comments should not say things like add 1 to Accumulator, jump to Start, or look at carry. You should describe how the program is aecting the system; internal eects on the CPU should be obvious from the code.
Keep comments brief and to the point. Details should be available elsewhere in the documentation. Comment all key points. Do not comment standard instructions or sequences that change counters or pointers; pay special attention to instructions that may not have an obvious meaning. Do not use obscure abbreviations. Make the comments neat and readable. Comment all denitions, describing their purposes. Also mark all tables and data storage areas. Comment sections of the program as well as individual instructions. Be consistent in your terminology. You can (should) be repetitive, you need not consult a thesaurus.
20
CHAPTER 2.
ASSEMBLERS
Leave yourself notes at points that you nd confusing: for example, remember carry was set by last instruction. If such points get cleared up later in program development, you may drop these comments in the nal documentation.
A well-commented program is easy to use. You will recover the time spent in commenting many times over. We will try to show good commenting style in the programming examples, although we often over-comment for instructional purposes.
2.6
Types of Assemblers
Although all assemblers perform the same tasks, their implementations vary greatly. We will not try to describe all the existing types of assemblers, we will merely dene the terms and indicate some of the choices. A
cross-assembler
is an assembler that runs on a computer other than the one for which it assembles
object programs. The computer on which the cross-assembler runs is typically a large computer with extensive software support and fast peripherals. The computer for which the cross-assembler assembles programs is typically a micro like the 6809 or MC68000. When a new microcomputer is introduced, a cross-assembler is often provided to run on existing development systems. For example, ARM provide the 'Armulator' cross-assembler that will run on a PC development system. A
self-assembler
or
resident assembler
assembles programs. The self-assembler will require some memory and peripherals, and it may run quite slowly compared to a cross-assembler. A A
macroassembler microassembler
is an assembler that allows you to dene sequences of instructions as macros. is an assembler used to write the microprograms which dene the instruction Microprogramming has nothing specically to do with programming micro-
set of a computer.
meta-assembler
is an assembler that can handle many dierent instruction sets. The user must
one-pass assembler
once. Such an assembler must have some way of resolving forward references, for example, Jump instructions which use labels that have not yet been dened. A
two-pass assembler
twice. The rst time the assembler simply collects and denes all the symbols; the second time it replaces the references with the actual denitions. A two-pass assembler has no problems with forward references but may be quite slow if no backup storage (like a oppy disk) is available; then the assembler must physically read the program twice from a slow input medium (like a teletypewriter paper tape reader). Most microprocessor-based assemblers require two passes.
2.7
Errors
Some
Assemblers normally provide error messages, often consisting of an error code number. typical errors are:
2.8.
LOADERS
Often a misspelling or an omitted denition Such as a 2 in a binary number A wrong delimiter or incorrect operands for example, two operators in a row Usually the value is too large Pretty self explanatory Two dierent values assigned to one name Such as a label on a pseudo-operation that cannot have one Probably a miss spelt lable name
21
Undened name Illegal character Illegal format Invalid expression Illegal value Missing operand Double denition Illegal label Missing label Undened operation code
In interpreting assembler errors, you must remember that the assembler may get on the wrong track if it nds a stray letter, an extra space, or incorrect punctuation. The assembler will Caution and then proceed to misinterpret the succeeding instructions and produce meaningless error messages. Always look at the rst error very carefully; subsequent ones may depend on it. consistent adherence to standard formats will eliminate many annoying mistakes.
2.8
Loaders
The loader is the program which actually takes the output (object code) from the assembler and places it in memory. Loaders range from the very simple to the very complex. We will describe a few dierent types. A
bootstrap loader
is a program that uses its own rst few instructions to load the rest of itself The assembler may place a
or another loader program into memory. The bootstrap loader may be in ROM, or you may have to enter it into the computer memory using front panel switches. bootstrap loader at the start of the object program that it produces. A
relocating loader
into the memory space immediately following that used by the previous program. The programs, however, must themselves be capable of being moved around in this way; that is, they must be relocatable. An memory. A
absolute loader,
linking loader
loads programs and subroutines that have been assembled separately; it resolves
cross-references that is, instructions in one program that refer to a label in another program. Object programs loaded by a linking loader must be created by an assembler that allows external references. An alternative approach is to separate the linking and loading functions and have the linking performed by a program called a
link editor
22
CHAPTER 2.
ASSEMBLERS
ARM Architecture
This chapter outlines the ARM processor's architecture and describes the syntax rules of the ARM assembler. Later chapters of this book describe the ARM's stack and exception processing system in more detail. Figure 3.1 on the following page shows the internal structure of the ARM processor. The ARM is a
type of system:
A large array of uniform registers. A load/store model of data-processing where operations can only operate on registers and not directly on memory. This requires that all data be loaded into registers before an operation can be preformed, the result can then be used for further processing or stored back into memory.
A small number of addressing modes with all load/store addresses begin determined from registers and instruction elds only. A uniform xed length instruction (32-bit).
In addition to these traditional features of a RISC system the ARM provides a number of additional features:
Separate
cessing to maximize execution speed. Auto-increment and Auto-decrement addressing modes to improve the operation of program loops. Conditional execution of instructions to reduce pipeline ushing and thus increase execution speed.
3.1
Processor modes
The ARM supports the seven processor modes shown in table 3.1. Mode changes can be made under software control, or can be caused by external interrupts or exception processing. Most application programs execute in User mode. While the processor is in User mode, the
program being executed is unable to access some protected system resources or to change mode, other than by causing an exception to occur (see 3.4 on page 29). This allows a suitably written operating system to control the use of system resources.
23
24
CHAPTER 3.
ARM ARCHITECTURE
3.2.
REGISTERS
25
Processor mode
User FIQ IRQ Supervisor Abort Undened System
Description
Normal program execution mode Fast Interrupt for high-speed data transfer Used for general-purpose interrupt handling A protected mode for the operating system Implements virtual memory and/or memory protection Supports software emulation of hardware coprocessors Runs privileged operating system tasks Table 3.1: ARM processor modes
privileged modes.
resources and can change mode freely. Five of them are known as
exception modes :
FIQ (Fast
Interrupt), IRQ (Interrupt), Supervisor, Abort, and Undened. These are entered when specic exceptions occur. Each of them has some additional registers to avoid corrupting User mode state when the exception occurs (see 3.2 for details). The remaining mode is System mode, it is not entered by any exception and has exactly the same registers available as User mode. However, it is a privileged mode and is therefore not subject to the User mode restrictions. It is intended for use by operating system tasks which need access to system resources, but wish to avoid using the additional registers associated with the exception modes. Avoiding such use ensures that the task state is not corrupted by the occurrence of any exception.
3.2
Registers
The ARM has a total of 37 registers. These comprise 30 general purpose registers, 6 status registers and a program counter. Figure 3.2 illustrates the registers of the ARM. Only fteen of the general purpose registers are available at any one time depending on the processor mode. There are a standard set of eight general purpose registers that are always available ( uses being placed on them by the processors' architecture. A few registers (
R0
R7 ) no
matter which mode the processor is in. These registers are truly general-purpose, with no special
R8
R12 )
q
mode. This means that to all intent and purpose these are general registers and have no special use. However, when the processor is in the fast interrupt mode these registers and replaced with dierent set of registers ( consider they to be
R8_q
R12_q ).
purpose to these registers they can be used to hold information between fast interrupts. You can
static
registers. The idea is that you can make a fast interrupt even faster
by holding information in these registers. The general purpose registers can be used to handle 8-bit bytes, 16-bit half-words , or 32-bit words. When we use a 32-bit register in a byte instruction only the least signicant 8 bits are used. In a half-word instruction only the least signicant 16 bits are used. Figure 3.3 demonstrates this. The remaining registers (
R13
R13
R15 )
usr)
R14
and System (
sys)
R15
is
exception modes all have their own version of these registers. Making a reference to register
R14
will assume you are referring to the register for the current processor mode. If you wish to refer
Although the ARM does allow for Half-Word instructions, the emulator we are using does not.
26
CHAPTER 3.
Modes Privileged Modes Exception Modes User R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 PC CPSR System R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 PC CPSR Supervisor R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13_svc R14_svc PC CPSR SPSR_svc Abort R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13_abt R14_abt PC CPSR SPSR_abt Undened R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13_und R14_und PC CPSR SPSR_und
ARM ARCHITECTURE
Fast Interrupt R0 R1 R2 R3 R4 R5 R6 R7 R8_q R9_q R10_q R11_q R12_q R13_q R14_q PC CPSR SPSR_q
Bit:
31
23
24
16
15
8-Bit Byte 16-Bit Half Word 32-Bit Word Figure 3.3: Byte/Half Word/Word
to the user mode version of this register you have refer to the mode other than user mode.
R14_usr
refer to register from other modes when the processor is in one of the privileged modes, i.e., any
There are also one or two status registers depending on which mode the processor is in. The Current Processor Status Register ( Register ( (including its current mode). In the exception modes there is an additional Saved Processor Status
SPSR)
which holds information on the processors state before the system changed into
R13
R13 ,
SP register.
The stack is typically used to store temporary values. It is normal to store the contents of any registers a function is going to use on the stack on entry to a subroutine. This leaves the register free for use during the function. The routine can then recover the register values from the stack
3.2.
REGISTERS
27
on exit from the subroutine. In this way the subroutine can preserve the value of the register and not corrupt the value as would otherwise be the case. See Chapter 15 for more information on using the stack.
R14
Link Register
or
LR.
It is used to hold the return address for a subroutine. When a subroutine call is performed via a
BL instruction, R14
ways:
is set to the address of the next instruction. To return from a subroutine you
need to copy the Link Register into the Program Counter. This is typically done in one of the two
MOV
PC, LR
or
BAL
LR
R14
STMFD LDMFD
This saves the Link Register on the stack at the start of the subroutine. On exit from the subroutine it collects all the values it placed on the stack, including the return address that was in the Link Register, except it returns this address directly into the Program Counter instead. See Chapter
?? on page ?? for further details of using the stack, and Chapter 15 on page 113 for
SPSR R14
is set to the address after the
further details on using subroutines. When an exception occurs, the exception mode's version of instruction which has just been completed. The
is a copy of the
CPSR
exception occurred. The return from an exception is performed in a similar way to a subroutine return, but using slightly dierent instructions to ensure full restoration of the state of the program that was being executed when the exception occurred. See 3.4 on page 29 for more details.
Program Counter known as the PC. It is used to identify which instruction next. As the PC holds the address of the next instruction it is often referred instruction pointer. The name program counter dates back to the times when program
holds the
R15
instructions where read in o of punched cards, it refers to the card position within a stack of cards. In spite of its name it does not actually count anything!
PC the value returned is the address of the current instruction plus after the next instruction to be executed 2 .
This is caused by the processor having already fetched the next instruction from memory while it was deciding what the current instruction was. Thus the PC is still the next instruction to be executed, but that is not the instruction immediately after the current one.
28
CHAPTER 3.
ARM ARCHITECTURE
instructions and data, including position-independent branching within a program. An exception to this rule occurs when an instruction stores
R15 .
STM
R15 .
The value stored is UNKNOWN and it is best to avoid the use of these
R15
instruction address and the system starts to execute the instruction at that address .
current processor status register (CPSR) contains the current status of the
processor. This includes various condition code ags, interrupt status, processor mode and other status and control information. The exception modes also have a the value of the
saved processor status register (SPSR), that is used to preserve CPSR when the associated exception occurs. Because the User and System modes
are not exception modes, there is no Figure 3.4 shows the format of the 31 N 30 Z 29 C
SPSR available.
and the
CPSR
27
SPSR
7 I
registers. 6 F 5 SBZ 4
28 V
SBZ
Mode
The processors' status is split into two distinct parts: the User ags and the Systems Control ags. The upper halfword is accessible in User mode and contains a set of ags which can be used to eect the operation of a program, see section 3.3. The lower halfword contains the System Control information. Any bit not currently used is reserved for future use and should be zero, and are marked SBZ in the gure. The
The
Mode
bits indicate which operating mode the processor is in (see 3.1 on page 23). The system ags can only be altered when the processor is in protected mode. User mode programs can not alter the status register except for the condition code ags.
3.3
Flags
The condition code ags are:
The upper four bits of the status register contains a set of four ags, collectively known at the
condition code.
3 As the processor has already fetched the instruction after the current instruction it is required to ush the instruction cache and start again. This will cause a short, but not signicant, delay.
3.4.
EXCEPTIONS
29
The condition code can be used to control the ow of the program execution. abbreviated to just
cc
The is often
The Negative (sign) ag takes on the value of the most signicant bit of a result. Thus when an operation produces a negative result the negative ag is set and a positive result results in a the negative ag being reset. This assumes the values are in standard two's complement form. If the values are unsigned the negative ag can be ignored or used to identify the value of the most signicant bit of the result.
Z C V
The Zero ag is set when an operation produces a zero result. operation produces a non-zero result.
It is reset when an
The Carry ag holds the carry from the most signicant bit produced by arithmetic operations or shifts. As with most processors, the carry ag is inverted after a subtraction so that the ag acts as a borrow ag after a subtraction. The Overow ag is set when an arithmetic result is greater than can be represented in a register.
Many instructions can modify the ags, these include comparison, arithmetic, logical and move instructions. Most of the instructions have an condition code ags or not.
3.4
Exceptions
Exceptions are generated by internal and external sources to cause the processor to handle an event, such as an externally generated interrupt or an attempt to execute an undened instruction. The ARM supports seven types of exception, and a provides a privileged processing mode for each type. Table 3.2 lists the type of exception and the processor mode associated with it. When an exception occurs, some of the standard registers are replaced with registers specic to the exception mode. All exception modes have their own Stack Pointer ( The fast interrupt mode has more registers (
R8_q
R12_q )
SP)
and Link (
LR)
registers.
Exception Type
Reset Software Interrupt Undened Instruction Prefetch Abort Data Abort Interrupt Fast Interrupt
Processor Mode
Supervisor Supervisor Undened Abort Abort IRQ FIQ
Reset
when the Reset pin is held low, this is normally when the system is rst turned on or when
Software Interrupt
The user program executes a software interrupt ( SWI, A.18 on page 135) instruction with a
is generally used to allow user mode programs to call the operating system.
30
CHAPTER 3.
ARM ARCHITECTURE
Undened Instruction
normally happens when there is a logical error in the program and the processor starts to execute data rather than program code.
occurs when the processor attempts to access memory that does not exist. The
lower two bits of a memory must be zero when accessing a word. occurs when an external device asserts the IRQ (interrupt) pin on the processor. This
can be used by external devices to request attention from the processor. An interrupt can not be interrupted with the exception of a fast interrupt.
Fast Interrupt
occurs when an external device asserts the FIQ (fast interrupt) pin.
This is
designed to support data transfer and has sucient private registers to remove the need for register saving in such applications. A fast interrupt can not be interrupted.
When an exception occurs, the processor halts execution after the current instruction. The state of the processor is preserved in the
program can be resumed when the exception routine has completed. The address of the instruction the processor was just about to execute is placed into the Link Register of the appropriate processor mode. The processor is now ready to begin execution of the exception handler. The exception handler are located a pre-dened locations known as
exception vectors.
It is the
3.5
Instruction Set
Why are a microprocessor's instructions referred to as an instruction set? Because the microprocessor designer selects the instruction complement with great care; it must be easy to execute complex operations as a sequence of simple events, each of which is represented by one instruction from a well-designed instruction set. Assembler often frighten users who are new to programming. Yet taken in isolation, the operations involved in the execution of a single instruction are usually easy to follow. Furthermore, you need not attempt to understand all the instructions at once. As you study each of the programs in these notes you will learn about the specic instructions involved. Table 4.1 lists the instruction mnemonics. This provides a survey of the processors capabilities, and will also be useful when you need a certain kind of operation but are either unsure of the specic mnemonics or not yet familiar with what instructions are available. See Chapter
??
and Appendix
??
chapters 7 through to 15 for a discussion on how to use them. The ARM instruction set can be divided into six broad classes of instruction.
Before we look at each of these groups in a little more detail there are a few ideas which belong to all groups worthy of investigation.
3.5.
INSTRUCTION SET
Operation Mnemonic Meaning Add with Carry Add Logical AND Unconditional Branch Branch on Condition Bit Clear Unconditional Branch and Link Conditional Branch and Link Compare Exclusive OR Load Multiple Load Register (Word) Load Register (Byte) Multiply Accumulate Move Load SPSR or CPSR Store to SPSR or CPSR Multiply Operation Mnemonic Meaning Logical NOT Logical OR Reverse Subtract Reverse Subtract with Carry Subtract with Carry Mult Accum Signed Long Multiply Signed Long Store Multiple Store Register (Word) Store Register (Byte) Subtract Software Interrupt Swap Word Value Swap Byte Value Test Equivalence Test Mult Accum Unsigned Long Multiply Unsigned Long
31
ADC ADD AND BAL B BIC BLAL BL CMP EOR LDM LDR LDRB MLA MOV MRS MSR MUL
cc
cc
MVN ORR RSB RSC SBC SMLAL SMULL STM STR STRB SUB SWI SWP SWPB TEQ TST UMLAL UMULL
Mnemonic
Condition arry
CS EQ VS GT GE PL HI HS
C S Eq v S G T G Pl Hi H S
et O erow reater igher or
Mnemonic
Condition arry ot
qual
ame (aka
CS)
CC NE VC LT LE MI LO LS
C C N E v C L T L E Mi Lo L S
lear O erow ess lear han ess Than or ower or ame
qual
nus (Negative)
CC)
Table 3.4:
cc
condition
dependent on the condition code ags (3.3 on page 28). If the ags indicate that the corresponding condition is true when the instruction starts executing, it executes normally. instruction does nothing. Table 4.2 on page 42 shows a list of the condition codes and their mnemonics. To indicate that an instruction is conditional we simply place the mnemonic for the condition code after the mnemonic for the instruction. If no condition code mnemonic is used the instruction will always be executed. For example the following instruction will move the value of the register only when the Carry ag has been set,
R0
R1
into the
R0
register
MOVCS
Note that the and
R0, R1
Greater
and the
Lower
Less
Higher
conditions are for use with unsigned numbers. These condition codes only really make
32
CHAPTER 3.
ARM ARCHITECTURE
Most data-processing instructions can also update the condition codes according to their result. versions of the
Placing an S after the mnemonic will cause the ags to be updated. For example there are two
MOV MOVS
MOV instruction: R0, #0 Will move the value 0 into the register R0 without setting the ags. R0, #0 Will do the same, move the value 0 into the register R0 , but it will
will be reset and the Carry and oVerow ags will not be eected.
also set
the condition code ags accordingly, the Zero ag will be set, the Negative ag
cc
MOV cc S
Rd , op1
With all this in mind what does the following code fragment do?
The rst instruction will move was zero. If the value of the value of
R1
into
R0
R1
and
ags
R1
to
R2 .
R2
into
R0
op1
An
op1
argument may come from one of two sources, a constant value or a register, and be
Unmodied Value
You can use a value or a register unmodied by simply giving the value or the register name. For example the following instructions will demonstrate the two methods:
MOV MOV
Will move the immediate constant value Will move the value in the register
123410
R0
R1
R0
bits. The number of bits to shift is specied by either a constant value or another register. The lower bits of the value are replaced with a zero. This is a simple way of performing a multiply by a power of 2 (2 ).
3.5.
INSTRUCTION SET
33
MOV MOV
R0 R0
R1
R1
R2
R2
register.
R1 shifted left by the number of bits R0 is the only register to change, both R1 C) is the last bit that was shifted out
If the instruction is to set the status register, the carry ag ( of the value.
bits. It will replace the upper bits with zeros, thus providing
2n
function (| 2
|).
MOV MOV
R0
value of
R1
R1 R2
The
As before
R0
R1
register.
R1
and
R2
If the instruction is to set the status register, the carry ag ( the value.
C)
2n
operation (2 ). Register
MOV MOV
R0 R0
R1
by 2 bits, with the sign maintained. Register will become the value of the register
right by the number of bits specied by the are not altered by this operation.
R2
R1
shifted to the
register.
R1
and
R2
Given the distinction between the Logical and Arithmetic Shift Right, why is there no Arithmetic Shift Left operation? As a signed number is stored in two's complement the upper most bits hold the sign of the number. These bits can be considered insignicant unless the number is of a sucient size to require their use. Thus an Arithmetic Shift Left is not required as the sign is automatically preserved by the Logical Shift.
Rotate Right
In the Rotate Right operation, the lest signicant bit is copied into the carry ( value of the
C)
in the value are lost, but are simply moved from the lower bits to the upper bits of the value.
34
CHAPTER 3.
ARM ARCHITECTURE
MOV
R1
of the resulting value will be the same as the least signicant bit of the original value. The second most signicant bit will be the same as the Carry ag. In the
second least signicant bit of the original value. The value of not changed by this operation.
R1
is
MOV
Register
R0
right by the number of bits specied by the are not altered by this operation. Why is there no corresponding Rotate Left operation?
R2
R1
rotated to the
register.
R1
and
R2
An Add With Carry ( ADC, A.1 on page 127) to a zero value provides this service for a single bit. The designers of the instruction set believe that a Rotate Left by more than one bit would never be required, thus they have not provided a ROL function.
C)
extended
ag into the most signicant bit of the value, and the least
C) ag.
though multi-word values, thereby allowing values larger than 32-bits to be used in calculations.
MOV
R0, R1 RRX
The register
R0
R1
rotated
though the carry ag by one bit. same as the least signicant bit or
becomes the same as the current Carry ag, while the Carry ag will be the
R1 .
R1
op2
page
??.
op2
??
on
op2
oset value of some form. This oset can be specied in one of three ways:
Constant Value
An immediate constant value can be provided. If no oset is specied an immediate constant value of zero is assumed.
Register
The oset can be specied by another register. The value of the register is added to the address held in another register to form the nal address.
Scaled
The oset is specied by another register which can be scaled by one of the shift operators used for
op1
ASR),
ROtate Right (
ROR)
3.5.
INSTRUCTION SET
35
Oset Addressing
oset addressing
In
LDR
R0, [R1]
R0
R1 .
R1
LDR R0, [R1, #4]
R0
dress calculated by adding the constant value 4 to the memory address contained in the
R1
register.
The register
R1
is not
LDR
R0
calculated by adding the value in the register held in the register this operation.
R2 .
R1
and
R2
R1
to the value
LDR
R0
address calculated by adding the value in the value obtained by shifting the value in registers,
R1
and
R2
R2
R1
register to the
This is particularly useful for indexing into a complex data structure. structure is held in a
base
register,
R1
the structure is then added to the base address. Placing the oset in a register allows it to be calculated at run time rather than xed. This allows for looping though a table.
A scaled value can also be used to access a particular item of a table, where the size of the item is a power of two. For example, to locate item 7 in a table of 32-bit values we need only shift the index value 6 left by 2 bits ( 6 of the table held in a register, is
22 )
R1
thus we use an index value of 6 rather than 7. A 32-bit number requires 4 bytes of storage which
22 ,
Pre-Index Addressing
pre-index addressing
In
the memory address if formed in the same way as for oset addressing.
The address is not only used to access memory, but the base register is also modied to hold the new value. In the ARM system this is known as a exclamation mark after at the end of the
op2
write-back
code.
Pre-Index address can be particularly useful in a loop as it can be used to automatically increment or decrement a counter or memory pointer.
36
CHAPTER 3.
ARM ARCHITECTURE
LDR
R0
with the word at the memory address register. The new memory address
calculated by adding the constant value 4 to the memory address contained in the
R1
R1 .
LDR
R0
R2 .
by this operation, the register holding the is modied to hold the new address.
LDR
First calculates the new address by adding the value in the base address register,
R1 ,
R2 ,
load the 32-bit at this address into the destination register, The new address is also written back into the base register, The oset register,
R2 ,
R0 . R1 .
Post-Index Addressing
In
post-index address
As a side-eect, an oset
is added to or subtracted from the base register value and the result is written back to the base register. Post-index addressing uses the value of the base register without modication. It then applies the modication to the address and writes the new address back into the base register. This can be used to automatically increment or decrement a memory pointer after it has been used, so it is pointing to the next location to be used. As the instruction must preform a write-back we do not need to include an exclamation mark. Rather we move the closing bracket to include only the base register, as that is the register holding the memory address we are going to access.
LDR
R0, [R1], #4
R0
R1 .
R1
R1 .
LDR
R0, [R1], R2
R0
R1 .
value for the base register by adding the value in the oset
R2 ,
oset register,
R2 ,
LDR
First loads the 32-bit value at the memory address contained in the base register,
R1 ,
R0 .
It will
then calculate the new value for the base register by adding the current value to the value obtained by shifting the value in the oset register,
R2 ,
R2 ,
will
Instruction Set
Why are a microprocessor's instructions referred to as an instruction set? Because the microprocessor designer selects the instruction complement with great care; it must be easy to execute complex operations as a sequence of simple events, each of which is represented by one instruction from a well-designed instruction set. Assembler often frighten users who are new to programming. Yet taken in isolation, the operations involved in the execution of a single instruction are usually easy to follow. Furthermore, you need not attempt to understand all the instructions at once. As you study each of the programs in these notes you will learn about the specic instructions involved. Table 4.1 lists the instruction mnemonics. This provides a survey of the processors capabilities, and will also be useful when you need a certain kind of operation but are either unsure of the specic mnemonics or not yet familiar with what instructions are available. The appendix A gives a detailed description of the individual instructions while chapters 7 through to 15 provide a discussion on how to use them. The ARM instruction set can be divided into six broad classes of instruction.
Before we look at each of these groups in a little more detail there are a few ideas which belong to all groups worthy of investigation.
Important Note:
The ARM instruction set can be divided into six broad classes of instruction:
Data-processing instructions (Data Movement) Branch instructions (Flow Control) Status register transfer instructions (Logic/Bit Bashing) Load and store instructions (Memory Access) Coprocessor instructions (System Control) Exception-generating instructions (Privileged)
37
38
CHAPTER 4.
Operation Mnemonic Meaning Add with Carry Add Logical AND Unconditional Branch Branch on Condition Bit Clear Unconditional Branch and Link Conditional Branch and Link Compare Exclusive OR Load Multiple Load Register (Word) Load Register (Byte) Multiply Accumulate Move Load SPSR or CPSR Store to SPSR or CPSR Multiply Operation Mnemonic Meaning
INSTRUCTION SET
ADC ADD AND BAL B BIC BLAL BL CMP EOR LDM LDR LDRB MLA MOV MRS MSR MUL
cc
cc
MVN ORR RSB RSC SBC SMLAL SMULL STM STR STRB SUB SWI SWP SWPB TEQ TST UMLAL UMULL
Logical NOT Logical OR Reverse Subtract Reverse Subtract with Carry Subtract with Carry Mult Accum Signed Long Multiply Signed Long Store Multiple Store Register (Word) Store Register (Byte) Subtract Software Interrupt Swap Word Value Swap Byte Value Test Equivalence Test Mult Accum Unsigned Long Multiply Unsigned Long
Arithmetic/logic instructions Comparison instructions Multiply instructions Count Leading Zeros instruction
Arithmetic/logic instructions
There are twelve arithmetic/logic instructions which share a common instruction format. These perform an arithmetic or logical operation on up to two source operands, and write the result to a destination register. They can also optionally update the condition code ags based on the result. Of the two source operands:
39
If the operand is a shifted register, the shift amount can be either an immediate value or the value of another register. Four types of shift can be specied. Every arithmetic/logic instruction can therefore perform an arithmetic/logic and a shift operation. As a result, ARM does not have dedicated shift instructions. Because the instructions.
Program Counter
can write their results directly to the PC. This allows easy implementation of a variety of jump
Comparison instructions
There are four comparison instructions which use the same instruction format as the arithmetic/logic instructions. These perform an arithmetic or logical operation on two source operands, but do not write the result to a register. They always update the condition ags based on the result. The source operands of comparison instructions take the same forms as those of arithmetic/logic instructions, including the ability to incorporate a shift operation.
Multiply instructions
Multiply instructions come in two classes. Both types multiply two 32-bit register values and store their result:
Normal. Stores the 32-bit result in a register. Long. Stores the 64-bit result in two separate registers.
set the values of the condition code ags set the values of the interrupt enable bits set the processor mode
40
CHAPTER 4.
INSTRUCTION SET
Load and Store Register Load and Store Multiple registers Swap register and memory contents
register
oset
base
In
oset addressing,
addressing. As a side-eect, the memory address is also written back to the base register. In the memory address is the base register value. As a side-eect,
an oset is added to or subtracted from the base register value and the result is written back to the base register.
In each case, the oset can be either an immediate or the value of an osets can also be scaled with shift operations.
index register.
Register-based
As the PC is a general-purpose register, a 32-bit value can be loaded directly into the PC to perform a jump to any address in the 4GB memory space.
The base address is specied by a register value, which can be optionally updated after the transfer. As the subroutine return address and PC values are in general-purpose registers, very ecient subroutine entry and exit sequences can be constructed with
LDM
and
STM:
41
A single
STM instruction at subroutine entry can push register contents and the return address LDM instruction at subroutine exit can restore register contents from the stack, load
onto the stack, updating the stack pointer in the process. A single
the PC with the return address, and update the stack pointer.
LDM and STM instructions also allow very ecient code for block copies and similar data movement
algorithms.
1. It loads a value from a register-specied memory location. 2. It stores the contents of a register to the same memory location. 3. It writes the value loaded in step 1 to a register.
By specifying the same register for steps 2 and 3, the contents of a memory location and a register are interchanged. The swap operation performs a special indivisible bus operation that allows atomic update of semaphores. Both 32-bit word and 8-bit byte semaphores are supported.
cur. These are normally used to make calls to an operating system, to request an OS-dened service. The exception entry caused by a in ways permitted by the OS.
sor mode. This allows an unprivileged task to gain access to privileged functions, but only
If
suitable debugger software is installed on the abort vector, an abort exception generated in this fashion is treated as a breakpoint. If debug hardware is present in the system, it can
BKPT
42
CHAPTER 4.
Mnemonic Condition arry
INSTRUCTION SET
CS EQ VS GT GE PL HI HS
C S Eq v S G T G Pl Hi H S
et O erow reater igher or
Mnemonic
Condition arry ot
qual
ame (aka
CS)
CC NE VC LT LE MI LO LS
C C N E v C L T L E Mi Lo L S
lear O erow ess lear han ess Than or ower or ame
qual
nus (Negative)
CC)
Table 4.2:
cc
In addition to the above, the following types of instruction cause an Undened Instruction exception to occur:
coprocessor instructions which are not recognized by any hardware coprocessor most instruction words that have not yet been allocated a meaning as an ARM instruction.
In each case, this exception is normally used either to generate a suitable error or to initiate software emulation of the instruction.
condition
dependent on the condition code ags (3.3 on page 28). If the ags indicate that the corresponding condition is true when the instruction starts executing, it executes normally. instruction does nothing. Table 4.2 shows a list of the condition codes and their mnemonics. To indicate that an instruction is conditional we simply place the mnemonic for the condition code after the mnemonic for the instruction. If no condition code mnemonic is used the instruction will always be executed. For example the following instruction will move the value of the register only when the Carry ag has been set,
R0
R1
into the
R0
register
MOVCS
Note that the and
R0, R1
Greater
and the
Lower
Less
Higher
conditions are for use with unsigned numbers. These condition codes only really make
Most data-processing instructions can also update the condition codes according to their result. versions of the
Placing an S after the mnemonic will cause the ags to be updated. For example there are two
MOV
MOV MOVS
R0, #0 R0, #0
R0
R0 ,
the condition code ags accordingly, the Zero ag will be set, the Negative ag will be reset and the Carry and oVerow ags will not be eected. If an instruction has this ability we denote it using
cc
43
MOV cc S
Rd , op1
With all this in mind what does the following code fragment do?
The rst instruction will move was zero. If the value of the value of
R1
into
R0
R1
and
ags
R1
to
R2 .
R2
into
R0
44
CHAPTER 4.
INSTRUCTION SET
5
5.1
Addressing Modes
op1
One of the operands
The majority of the instructions relate to data processing of some form. modied before it is used.
to these instructions is routed through the Barrel Shifter. This means that the operand can be This can be very useful when dealing with lists, tables and other complex data structures. We denote instructions of this type as taking one of its arguments from
op1
An
op1
argument may come from one of two sources, a constant value or a register, and be
MOV MOV
Will move the immediate constant value Will move the value in the register
123410
R0
R1
R0
This will take the value of a register and shift the value up, towards the most signicant bit, by
bits. The number of bits to shift is specied by either a constant value or another register. The lower bits of the value are replaced with a zero. This is a simple way of performing a multiply by a power of 2 (2 ).
MOV MOV
R0 R0
R1
R1
R2
R2
register.
R1 shifted left by the number of bits R0 is the only register to change, both R1 C) is the last bit that was shifted out
If the instruction is to set the status register, the carry ag ( of the value.
45
46
CHAPTER 5.
ADDRESSING MODES
Logical Shift Right is very similar to Logical Shift Left except it will shift the value to the right, towards the lest signicant bit, by an ecient unsigned divide by
bits. It will replace the upper bits with zeros, thus providing
2n
function (| 2
|).
MOV MOV
R0
value of
R1
R1 R2
The
As before
R0
R1
register.
R1
and
R2
If the instruction is to set the status register, the carry ag ( the value.
C)
The Arithmetic Shift Right is rather similar to the Logical Shift Right, but rather than replacing the upper bits with a zero, it maintains the value of the most signicant bit. As the most signicant bit is used to hold the sign, this means the sign of the value is maintained, thus providing a signed divide by
2n
operation (2 ). Register
MOV MOV
R0 R0
R1
by 2 bits, with the sign maintained. Register will become the value of the register
right by the number of bits specied by the are not altered by this operation.
R2
R1
shifted to the
register.
R1
and
R2
Given the distinction between the Logical and Arithmetic Shift Right, why is there no Arithmetic Shift Left operation? As a signed number is stored in two's complement the upper most bits hold the sign of the number. These bits can be considered insignicant unless the number is of a sucient size to require their use. Thus an Arithmetic Shift Left is not required as the sign is automatically preserved by the Logical Shift.
In the Rotate Right operation, the lest signicant bit is copied into the carry ( value of the
C)
in the value are lost, but are simply moved from the lower bits to the upper bits of the value.
5.2.
OP2
47
MOV
R1
of the resulting value will be the same as the least signicant bit of the original value. The second most signicant bit will be the same as the Carry ag. In the
second least signicant bit of the original value. The value of not changed by this operation.
R1
is
MOV
Register
R0
right by the number of bits specied by the are not altered by this operation. Why is there no corresponding Rotate Left operation?
R2
R1
rotated to the
register.
R1
and
R2
An Add With Carry ( ADC, A.1 on page 127) to a zero value provides this service for a single bit. The designers of the instruction set believe that a Rotate Left by more than one bit would never be required, thus they have not provided a ROL function.
This is similar to a Rotate Right by one bit. The moves the value of the Carry (
C)
extended
ag into the most signicant bit of the value, and the least
C) ag.
though multi-word values, thereby allowing values larger than 32-bits to be used in calculations.
MOV
R0, R1 RRX
The register
R0
R1
rotated
though the carry ag by one bit. same as the least signicant bit or
becomes the same as the current Carry ag, while the Carry ag will be the
R1 .
R1
5.2
op2
The memory address used in the memory access instructions may also modied by the barrel shifter. This provides for more advanced access to memory which is particularly useful when dealing with more advanced data structures. It allows pre- and post-increment instructions that update memory pointers as a side eect of the instruction. This makes loops which pass though memory more ecient. We denote instructions of this type as taking one of its arguments from
op2
page
??.
op2
??
on
op2
oset value of some form. This oset can be specied in one of three ways:
Constant Value
An immediate constant value can be provided. If no oset is specied an immediate constant value of zero is assumed.
Register
The oset can be specied by another register. The value of the register is added to the address held in another register to form the nal address.
48
CHAPTER 5.
ADDRESSING MODES
Scaled
The oset is specied by another register which can be scaled by one of the shift operators used for
op1
ASR),
ROtate Right (
ROR)
In
oset addressing
LDR
R0, [R1]
R0
R1 .
R1
LDR R0, [R1, #4]
R0
dress calculated by adding the constant value 4 to the memory address contained in the
R1
register.
The register
R1
is not
LDR
R0
calculated by adding the value in the register held in the register this operation.
R2 .
R1
and
R2
R1
to the value
LDR
R0
address calculated by adding the value in the value obtained by shifting the value in registers,
R1
and
R2
R2
R1
register to the
This is particularly useful for indexing into a complex data structure. structure is held in a
base
register,
R1
the structure is then added to the base address. Placing the oset in a register allows it to be calculated at run time rather than xed. This allows for looping though a table. A scaled value can also be used to access a particular item of a table, where the size of the item is a power of two. For example, to locate item 7 in a table of 32-bit values we need only shift the index value 6 left by 2 bits ( 6 of the table held in a register, is
22 )
R1
thus we use an index value of 6 rather than 7. A 32-bit number requires 4 bytes of storage which
22 ,
5.2.
OP2
49
In
pre-index addressing
the memory address if formed in the same way as for oset addressing.
The address is not only used to access memory, but the base register is also modied to hold the new value. In the ARM system this is known as a exclamation mark after at the end of the
op2
write-back
code.
Pre-Index address can be particularly useful in a loop as it can be used to automatically increment or decrement a counter or memory pointer.
LDR
R0
with the word at the memory address register. The new memory address
calculated by adding the constant value 4 to the memory address contained in the
R1
R1 .
LDR
R0
R2 .
by this operation, the register holding the is modied to hold the new address.
LDR
First calculates the new address by adding the value in the base address register,
R1 ,
R2 ,
load the 32-bit at this address into the destination register, The new address is also written back into the base register, The oset register,
R2 ,
R0 . R1 .
In
post-index address
As a side-eect, an oset
is added to or subtracted from the base register value and the result is written back to the base register. Post-index addressing uses the value of the base register without modication. It then applies the modication to the address and writes the new address back into the base register. This can be used to automatically increment or decrement a memory pointer after it has been used, so it is pointing to the next location to be used.
50
CHAPTER 5.
ADDRESSING MODES
As the instruction must preform a write-back we do not need to include an exclamation mark. Rather we move the closing bracket to include only the base register, as that is the register holding the memory address we are going to access.
LDR
R0, [R1], #4
R0
R1 .
R1
R1 .
LDR
R0, [R1], R2
R0
R1 .
value for the base register by adding the value in the oset
R2 ,
oset register,
R2 ,
LDR
First loads the 32-bit value at the memory address contained in the base register,
R1 ,
R0 .
It will
then calculate the new value for the base register by adding the current value to the value obtained by shifting the value in the oset register,
R2 ,
R2 ,
will
Programs
The only way to learn assembly language programming is through experience. Throughout the rest of this book each chapter will introduce various aspects of assembly programming. The chapter will start with a general discussion, then move on to a number of example programs which will demonstrate the topic under discussion. problems for you to try. The chapter will end with a number of programming
6.1
Example Programs
that describes the general problem statement of purpose that describes the task the program performs and the memory locations used. A sample problem complete with data and results. if the program logic is complex. for the assembly program. Explanatry notes that discusses the instructions and methods used in the program.
Each example is written and assembled as a stand-alone program. They can be downloaded from the web site .
should be aware of the fact that you can generate a listing le. See the section on the ARMulator environment which follows for details of how to generate a
1. Standard ARM assembler notation is used, as summarized in Chapter 2. 2. The forms in which data and addresses appear are selected for clarity rather than for consistency. We use hexadecimal numbers for memory addresses, instruction codes, and BCD data; decimal for numeric constants; binary for logical masks; and ASCII for characters.
1 http://dec.bournemouth.ac.uk/support/sem/sysarch/examples.zip
51
52
CHAPTER 6.
3. Frequently used instructions and programming techniques are emphasized.
PROGRAMS
4. Examples illustrate tasks that microprocessors perform in communication, instrumentation, computers, business equipment, industrial, and military applications. 5. Detailed comments are included. 6. Simple and clear structures are emphasised, but programs are written as eciently as possible within this guideline. Notes accompanying programs often describe more ecient procedures. 7. Program are written as an independent procedures or subroutines although no assumptions are made concerning the state of the microprocessor on entry to the procedure. 8. Program end with a this by replacing the
(Software Interrupt) instruction. You may prefer to modify instruction with an endless loop instruction such as:
HERE
BAL
HERE
9. Programs use standard ARM assembler directives. We introduced assembler directives conceptually in Chapter 2. When rst examining programming examples, you can ignore the assembler directives if you do not understand them. Assembler directives do not contribute to program logic, which is what you will be trying to understand initially; but they are a necessary part of every assembly language program, so you will have to learn how to use them before you write any executable programs. Including assembler directives in all program examples will help you become familiar with the functions they perform.
6.2
To test one of the example programs, rst obtain a copy of the source code. The best way of doing this is to type in the source code presented in this book, as this will help you to understand the code. Alternatively you can download the source from the web site, although you won't gain the same knowledge of the code. Go to the start menu and call up the Armulate program. Next open the source le using the normal File | Open menu option. within the Armulate environment. The next step is to create a new Project within the environment. Select the Project menu option, then New. Give your project the same name as the source le that you are using (there is no need to use a le extension it will automatically be saved as a This will open your program source in a separate window
.apj
le).
Once you have given the le a name, a further dialog will open as shown in the gure 6.1 on the next page. Click the Add button, and you will again be presented with a le dialog, which will display the source les in the current directory. Select the relevant source le and OK the dialog. You will be returned to the previous dialog, but you will see now that your source le is included in the project. OK the Edit Project dialog, and you will be returned to the Armulate environment, now with two windows open within it, one for the source code and one for the project. We recommend that you always create a
.list
this by selecting the Options menu with the project window in focus, then the Assembler item. This will open the dialog shown in gure 6.2 on the facing page. Enter
-list [yourfilename].list
You have now created your project and are ready to assemble and debug your code. Additional information on the Armulator is available via the help menu item.
6.3.
53
6.3
When developing the example programs, we found the Armulate environment too clumsy. We used the TextPad editor and assembled the programs from the command line. environment provides commands for use from the command line:
1. Assembler The command line assembler is used to create an object le from the program source code. During the development of the add program (program 7.3a) we used the command line:
add.o
add
load image.
ARMSD add
However, the command driven nature of this system is confusing and hard to use for even the most experienced of developers. Thus we suggest you use the windows based debugger program:
54
CHAPTER 6.
PROGRAMS
WINDBG add
Which will provide you with the same debugger you would have seen had you used the Window based Armulate environment.
Syntax Denition sub-section of the Add-ons section of the Download armasm.syn from the arm.zip le into the TextPad Samples directory.
page.
Having installed the Syntax Denitions you should now add a new Document Class to TextPad. Run TextPad and select the
Congure menu.
The wizard
will now take you though the following steps: 1. The Document Class requires a name. We have used the name ARM
Assembler .
We
2. The Class Members, the le name extension to associate with this document class. associate all
.s
and
.list
3. Syntax Highlighting. The next dialog is where we tell TextPad to use syntax highlighting, simply check the Enable Syntax Highlighting box. denition le to use. If the
armasm.syn
Samples
While this will create the new document class, you will almost certainly want to change the colour settings for this document class. This class uses the dierent levels of Keyword colouring for dierent aspects of the syntax as follows:
1 2 3 4 5 6
Instructions Co-processor and pseudo-instructions Shift-addresses and logical directives Registers Directives Arguments and built-in names
You will probably want to set the color ( sic ) setting for all of these types to the same settings. We have set all but Keywords 2 to the same colour scheme. To alter the color setting you should select the
Preferences. . .
Congure
menu.
In the Preference dialog (shown in gure 6.4 on the next page), open the section and then your new document class (
ARM Assembler ).
section. This will now allow you to change the colours for any of the given color settings. Finally you may like to consider adding a File Type Filter to the Open File dialog. can be done by selecting the
New button, add the description (ARM Assembler (*.s, *.list)) and wildcard (*.s;*.list) details. Finally click on the OK button.
(without spaces) in the wildcard entry.
entry in the
Preference
Note the use of a comma to seperate the wildcards in the description, and the use of a semi-colon
2 http://www.textpad.com
6.4.
PROGRAM INITIALIZATION
55
6.4
Program Initialization
Often this requires additional instructions that may
All of the programming examples presented in these notes pay particular attention to the correct initialization of constants and operands. appear superuous, in that they do not contribute directly to the solution of the stated problem. Nevertheless, correct initialization is important in order to ensure the proper execution of the program every time. We want to stress correct initialization; that is why we are going to emphasize this aspect of problems.
6.5
Special Conditions
For the same reasons that we pay particular attention to special conditions that can cause a program to fail. Empty lists and zero indexes are two of the most common circumstances overlooked in sample problems. It is critically important when using microprocessors that you learn with your very rst program to anticipate unusual circumstances; they frequently cause your program to fail. You must build in the necessary programming steps to account for these potential problems.
6.6
Problems
You should use the
Each chapter will now end with a number of programming problems for your to try. They have been provided to help you understand the ideas presented in the chapter.
56
CHAPTER 6.
PROGRAMS
programming examples as guidelines for solving the problems. Don't forget to run your solutions on the ARMulator to ensure that they are correct. The following guidelines will help in solving the problems:
1. Comment each program so that others can understand it. The comments can be brief and ungrammatical. They should explain the purpose of a section or instruction in the program, but should not describe the operation of instructions, that description is available in manuals. For example the following line:
ADD
R1, R1, #1
why
the line is there. They tell us
could be given the comment Add one to R1 or Increment R1, both of which provide no indication as to
what
tell that by looking at the instruction itself. We are more interested in why the instruction is there. A comment such as Increment loop counter is much more useful as it explains why you are adding one to
R1 ,
You do not have to comment each statement or explain the obvious. You may follow the format of the examples but provide less detail. 2. Emphasise clarity, simplicity, and good structure in programs. While programs should be reasonably ecient, do not worry about saving a single byte of program memory or a few microseconds. 3. Make programs reasonably general. Do not confuse parameters (such as the number of
elements in any array) with xed constants (such as the code for the letter C). 4. Never assume xed initial values for parameters. 5. Use assembler notation as shown in the examples and dened in Chapter 2. 6. Use symbolic notation for address and data references. used even for constants (such as possible form for data (such as Symbolic notation should also be Also use the clearest
7. Use meaningful names for labels and variables, e.g., 8. Execute each program with the emulator. program is correct. program works for special cases.
CHECK
rather than
or
Z.
Data Movement
features of the ARM. In addition, these programs demonstrate some primitive tasks that are common to assembly language programs for many dierent applications.
7.1
Program Examples
Value
Result.
Value Result
= =
C123 C123
Program 7.1:
move16.s
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
; 16-Bit data transfer TTL AREA ENTRY Main LDRB STR SWI DCW ALIGN DCW END Ch4ex1 - move16 Program, CODE, READONLY
; Load the value to be moved ; Store it back in a different location ; Value to be moved ; Need to do this because working with 16bit value ; Storage space
Value Result
This program solves the problem in two simple steps. The rst instruction loads data register with the 16-bit value in location register
R1
in location
Result.
Value.
R1
As a reminder of the necessary elements of an assembler program for the ARMulator, notice that this, and all the other example programs have the following elements. Firstly there must be an
ENTRY
AREA directive, at the start of the program, and there may be other AREA directives to dene data storage areas. Finally there must be an END directive, to show where
there must be at least one the code ends. The absence of any of these will cause the assembly to fail with an error. Another limitation to bear in mind is that ARMulator instructions will only deal with bits) or
directive. This tells the assembler where the rst executable instruction is located. Next
WORD
HALF-WORD
BYTE
(8
57
58
CHAPTER 7.
DATA MOVEMENT
by the use
of the of the
DCW directive, but it is necessary to ensure consistency of storage of HALF-WORD ALIGN directive. You can see the use of this in the rst worked example.
In addition, under the RISC architecture of the ARM, it is not possible to directly manipulate data in storage. Even if no actual manipulation of the data is taking place, as in this rst example, it is necessary to use the This version of the
LDR or LDRB and STR or STRB to move data to a dierent area of memory. STR Value
instruction at the memory location specied by
LDR
Result.
Notice that, by default, every program is allocated a literal pool (a storage area) after the last executable line. In the case of this, and most of the other programs, we have formalised this by the use of the
AREA
Data1, DATA
Value.
Value Result
= =
C123 FFFF3EDC
Program 7.2:
invert.s
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
; Find the one's compliment (inverse) of a number TTL AREA ENTRY Main LDR MVN STR SWI DCD DCD END Ch4Ex2 - invert Program, CODE, READONLY
; Load the number to be complimented ; NOT the contents of R1 ; Store the result ; Value to be complemented ; Storage for result
Value Result
Value into data register R1 . The next instruction MVN takes the logical complement of data register R1 . Finally, in the third instruction the result of the logical complement is stored in Value.
location Note that any data register may be referenced in any instruction that uses data registers, but note the use of been used. The Thus, in the
R15 for the program counter, R14 for the link register and R13 for the stack pointer. LDR instruction we've just illustrated, any of the general purpose registers could have
STR
instructions in this program, like those in Program 7.1, demonstrate one of The data reference to
LDR
and
Value
referenced (less 8 byes) is contained in the extension word(s) following the operation word of the instruction. As shown in the assembly listing, the oset to the address corresponding to found in the extension word for the
LDR
and
STR
Value
is
instructions.
7.1.
PROGRAM EXAMPLES
59
Value1 Result.
Value2
and
= = =
Output:
Program 7.3a:
add.s
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
; Add two (32-Bit) numbers TTL AREA ENTRY Main LDR LDR ADD STR SWI DCD DCD DCD END Ch4Ex3 - add Program, CODE, READONLY
; ; ; ;
Load the first number Load the second number ADD them together into R1 (x = x + y) Store the result
&37E3C123 &367402AA 0
The
ADD
LDR
instruction, this instruction's third operand not only represents the instruction's destination but may also be used to calculate the result. The format:
DESTINATION
SOURCE1
operation
SOURCE2
is common to many of the instructions. As with any microprocessor, there are many instruction sequences you can execute which will solve the same problem. Program 7.3b, for example, is a modication of Program 7.3a and uses oset addressing instead of immediate addressing. Program 7.3b:
add2.s
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
; Add two numbers and store the result TTL AREA ENTRY Main LDR LDR ADD LDR ADD LDR STR SWI Ch4Ex4 - add2 Program, CODE, READONLY
; ; ; ; ; ; ; ;
Load the address of first value Load what is at that address Adjust the pointer Load what is at the new addr ADD together Load the storage address Store the result All done
60
CHAPTER 7.
DATA MOVEMENT
17 18 19 20 21
&37E3C123 &367402AA 0
The
ADR
have not used previously. Immediate addressing lets you dene a data constant and include that constant in the instruction's associated object code. The assembler format identies immediate addressing with a # preceding the data constant. The size of the data constant varies depending on the instruction. Immediate addressing is extremely useful when small data constants must be referenced. The
ADR
use of the
LDR
to indicate that the address of the data should be loaded rather than the data itself.
The second addressing mode oset addressing uses immediate addressing to load a pointer to a memory address into one of the general purpose registers. Program 7.3b also demonstrates the use of base register plus oset addressing. In this example we have performed this operation manually on line 10 ( ADD address stored in
R0
by 4 bytes or one
WORD.
doing this, such as pre-index or post-index addressing which we will see in later examples. Another advantage of this addressing mode is its faster execution time as compared to immediate addressing. This improvement occurs because the address extension word(s) does not have to be fetched from memory prior to the actual data reference, after the initial fetch. A nal advantage is the exibility provided by having
R0
part of the instruction. This exibility allows the same code to be used for more than one address. Thus if you wanted to add the values contained in consecutive variables could simply change the contents of
R0 .
Value3
and
Value4,
you
Result.
Value Result
= =
4242 8484
Program 7.4:
shiftleft.s
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
; Shift Left one bit TTL AREA ENTRY Main LDR MOV STR SWI DCD DCD END Ch4Ex5 - shiftleft Program, CODE, READONLY
R1, Value R1, R1, LSL #0x1 R1, Result &11 &4242 0
; Load the value to be shifted ; SHIFT LEFT one bit ; Store the result ; Value to be shifted ; Space to store result
Value Result
7.1.
PROGRAM EXAMPLES
61
The
MOV
instruction is used to perform a logical shift left. Using the operand format of the
MOV
instruction shown in Program 7.4, a data register can be shifted from 1 to 25 bits on either a byte, word or longword basis. Another form of the in another data register.
LSL
Result.
Value
into two 4-bit nibbles and store one The high-order four bits of the
Result.
byte will be stored in the low-order four bits of the most signicant byte of Sample Problems
Input: Output:
Result.
Value Result
= =
5F 050F
Program 7.5:
nibble.s
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
; Disassemble a byte into its high and low order nibbles TTL AREA ENTRY Main LDR LDR MOV MOV AND ADD STR SWI Value Mask Result DCB ALIGN DCW ALIGN DCD END Ch4Ex6 - nibble Program, CODE, READONLY
Value Mask R1, LSR #0x4 R3, LSL #0x8 R1, R2 R1, R3
; ; ; ; ; ; ; ;
Load the value to be disassembled Load the bitmask Copy just the high order nibble into R3 Now left shift it one byte AND the original number with the bitmask Add the result of that to What we moved into R3 Store the result
; Value to be shifted ; Keep the memory boundaries ; Bitmask = %0000000000001111 ; Space to store result
B sux, all the LDRinstructions in Program 7.5 LDRB instructions, therefore performing byte operations. The STR instruction must remain, since we are storing a halfword value. If we were only dealing with a one byte result, we could use the STRB byte version of the store instruction.
words also to operate on bytes. Thus, by using the become Remember that the
This is an example of byte manipulation. The ARM allows most instructions which operate on
MOV
MOV
instruction is quite frequent. Generally, it is more ecient in terms of program memory usage and execution time to minimise references to memory.
62
CHAPTER 7.
DATA MOVEMENT
Result.
Input:
Output:
Program 7.6:
bigger.s
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
; Find the larger of two numbers TTL AREA ENTRY Main LDR LDR CMP BHI MOV STR SWI DCD DCD DCD END Ch4Ex7 - bigger Program, CODE, READONLY
Done
R1, Value1 R2, Value2 R1, R2 Done R1, R2 R1, Result &11 &12345678 &87654321 0
; ; ; ; ;
Load the first value to be compared Load the second value to be compared Compare them If R1 contains the highest otherwise overwrite R1
; Store the result ; Value to be compared ; Value to be compared ; Space to store result
SUB.
CMP, sets the status register ags as if the destination, R1 , were subR2 . The order of the operands is the same as the operands in the subtract BHI
transfers control to the statement labeled
R2
Done, register R2
R1 .
Done
if the
BHI
BHI
to
BGE
R1, R2 Done
You can use the following table 7.1 to use when performing signed and unsigned comparisons. Note that the same instructions are used for signal and unsigned addition, subtraction, or comparison; however, the comparison operations are dierent. The conditional branch instructions are an example of program counter relative addressing. In other words, if the branch condition is satised, control will be transfered to an address relative
7.1.
PROGRAM EXAMPLES
63
Compare Condition
greater than or equal greater than equal not equal less than or equal less than
Signed
BGE BGT BEQ BNE BLE BLT
Unsigned
BHS BHI BEQ BNE BLS BLO
to the current value of the program counter. Dealing with compares and branches is an important part of programming. Don't confuse the sense of the tested is:
CMP instruction.
DESTINATION
condition
SOURCE
For exampe, if the condition is less than, then you test for destination less than source. Become familiar with all of the conditions and their meanings. Unsigned compares are very useful when comparing two addresses.
Value1
and
Value2.
Result.
= = =
Program 7.7:
add64.s
64 bit addition
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
; 64 bit addition TTL AREA ENTRY Main LDR LDR LDR LDR LDR LDR ADDS ADC LDR STR STR SWI Value1 Value2 Result DCD DCD DCD END Ch4Ex8 - add64 Program, CODE, READONLY
R0, R1, R2, R0, R3, R4, R6, R5, R0, R5,
=Value1 [R0] [R0, #4] =Value2 [R0] [R0, #4] R2, R4 R1, R3 =Result [R0]
; ; ; ; ; ; ; ; ; ;
Pointer to first value Load first part of value1 Load lower part of value1 Pointer to second value Load upper part of value2 Load lower part of value2 Add lower 4 bytes and set carry flag Add upper 4 bytes including carry Pointer to Result Store upper part of result
; Store lower part of result ; Value to be added ; Value to be added ; Space to store result
64
CHAPTER 7.
DATA MOVEMENT
Here we introduce several important and powerful instructions from the ARM instruction set. As before, at line 8 we use the of
Value1.
value,
R0 to hold the starting address R1, [R0] fetches the rst 4 bytes (32-bits) of the 64-bit starting at the location pointed to by R0 and places them in the R1 register. Line 10 loads
LDR
instruction which causes register At line 9 the instruction
LDR
the second 4 bytes or the lower half of the 64-bit value from the memroy address pointed to by
R0
#4]. Between them R1 and R2 now hold the rst R2 has the lower half. Lines 1113 repeat this process into R3 and R4 .
word s,
held in
64-bit value,
R1
has
R2
and
R4
R6 .
This forces
This is all straightforward, but note now the use of the the update of the ags as a result of the
ADD operation.
results in a carry, the carry ag bit will be set. Now the
R3 ,
ADC (add with carry) instruction is used to add the two high order word s, held in R1
and
but taking into account any carry resulting from the previous addition.
Finally, the result is stored using the same technique as we used the load the values (lines 1618).
Result.
(0! (1! (2! (3! (4! (5! (6! (7!
Assume
Value from a table of factorials DataTable. Value has a value between 0 and 7.
1 10 ) 1 10 ) 2 10 ) 6 10 ) 24 10 )
Store the
FTABLE
= = = = = = = = = =
= = = = = = = =
Value
Output:
Result
(5!
120 10 )
location
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
Program 7.8:
factorial.s Lookup the factorial from a table by using the address of the memory
; Lookup the factorial from a table using the address of the memory location TTL AREA ENTRY Main LDR LDR MOV ADD LDR LDR STR SWI Ch4Ex9 - factorial Program, CODE, READONLY
R0, =DataTable R1, Value R1, R1, LSL #0x2 R0, R2, R3, R2, &11 R0, R1 [R0] =Result [R3]
; ; ; ; ; ;
Load the address of the lookup table Offset of value to be looked up Data is declared as 32bit - need to quadruple the offset to point at the correct memory location R0 now contains memory address to store
; The address where we want to store the answer ; Store the answer
7.2.
PROBLEMS
65
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
AREA DCD DCD DCD DCD DCD DCD DCD DCD DCB ALIGN DCW END
DataTable, DATA 1 1 2 6 24 120 720 5040 5 0 ;0! ;1! ;2! ;3! ;4! ;5! ;6! ;7! = = = = = = = = 1 1 2 6 24 120 720 5040 ; The data table containing the factorials
Value Result
The approach to this table lookup problem, as implemented in this program, demonstrates the use of oset addressing. The rst two the lookup table , and register
R1
LDR
contents of
Value.
R0
LSL #0x2
The actual calculation of the entry in the table is determined by the rst operand of the instruction. The long word contents of address register
R0
R1
R1, R1,
to form the eective address used to index the table entry. When
R0
7.2
Problems
VALUE
RESULT.
VALUE RESULT
3E2A42A1 21F260A0
Output:
3E2A42A1 21F260A0
VALUE1.
Output:
VALUE
Note that we are using a LDR instruction as the data table is sucently far away from the instruction that an
66
CHAPTER 7.
DATA MOVEMENT
Sample Problems
Input: Output:
VALUE VALUE
LIST
into the most signicant nibble of the result. Store the result
LIST
0C 02 06 09
Output:
RESULT
0000C269
VALUE1, VALUE2
and
Output:
RESULT.
VALUE1
and word
VALUE2
Output:
That is or
bits
VALUE
left. The number of bits to shift is contained in the word
Assume that the shift count is less than 32. The low-order bits should be cleared.
Sample Problems
Input:
Output:
7.2.
PROBLEMS
67
In the rst case the value is to be shifted left by three bits, while in the second case the same value is to be shifted by thirty two bits.
68
CHAPTER 7.
DATA MOVEMENT
8
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
Logic
Program 8.7a:
bigger.s
; Find the larger of two numbers TTL AREA ENTRY Main LDR LDR CMP BHI MOV STR SWI DCD DCD DCD END Ch4Ex7 - bigger Program, CODE, READONLY
Done
R1, Value1 R2, Value2 R1, R2 Done R1, R2 R1, Result &11 &12345678 &87654321 0
; ; ; ; ;
Load the first value to be compared Load the second value to be compared Compare them If R1 contains the highest otherwise overwrite R1
; Store the result ; Value to be compared ; Value to be compared ; Space to store result
Program 8.7a:
add64.s
64 bit addition
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
; 64 bit addition TTL AREA ENTRY Main LDR LDR LDR LDR LDR LDR ADDS ADC LDR STR STR SWI Value1 Value2 Result DCD DCD DCD END
69
R0, R1, R2, R0, R3, R4, R6, R5, R0, R5,
=Value1 [R0] [R0, #4] =Value2 [R0] [R0, #4] R2, R4 R1, R3 =Result [R0]
; ; ; ; ; ; ; ; ; ;
Pointer to first value Load first part of value1 Load lower part of value1 Pointer to second value Load upper part of value2 Load lower part of value2 Add lower 4 bytes and set carry flag Add upper 4 bytes including carry Pointer to Result Store upper part of result
; Store lower part of result ; Value to be added ; Value to be added ; Space to store result
70
CHAPTER 8.
LOGIC
Program 8.7a:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
; Lookup the factorial from a table using the address of the memory location Ch4Ex9 - factorial Program, CODE, READONLY
R0, =DataTable R1, Value R1, R1, LSL #0x2 R0, R2, R3, R2, &11 DataTable, DATA 1 1 2 6 24 120 720 5040 5 0 ;0! ;1! ;2! ;3! ;4! ;5! ;6! ;7! = = = = = = = = R0, R1 [R0] =Result [R3]
; ; ; ; ; ;
Load the address of the lookup table Offset of value to be looked up Data is declared as 32bit - need to quadruple the offset to point at the correct memory location R0 now contains memory address to store
; The address where we want to store the answer ; Store the answer
Value Result
Program Loops
The program loop is the basic structure that forces the CPU to repeat a sequence of instructions. Loops have four sections: 1. The initialisation section, which establishes the starting values of counters, pointers, and other variables. 2. The processing section, where the actual data manipulation occurs. This is the section that does the work. 3. The loop control section, which updates counters and pointers for the next iteration. 4. The concluding section, that may be needed to analyse and store the results. The computer performs Sections 1 and 4 only once, while it may perform Sections 2 and 3 many times. Therefore, the execution time of the loop depends mainly on the execution time of Sections 2 and 3. Those sections should execute as quickly as possible, while the execution times of Sections 1 and 4 have less eect on overall program speed. There are typically two methods of programming a loop, these are the repeat . . . until loop (Algorithm 9.1a) and the while loop (Algorithm 9.1b). The repeat-until loop results in the computer always executing the processing section of the loop at least once. On the other hand, the computer may not execute the processing section of the while loop at all. The repeat-until loop is more natural, but the while loop is often more ecient and eliminates the problem of going through the processing sequence once even where there is no data for it to handle. The computer can use the loop structure to process large sets of data (usually called arrays). The simplest way to use one sequence of instructions to handle an array of data is to have the program increment a register (usually an index register or stack pointer) after each iteration. Then the register will contain the address of the next element in the array when the computer repeats the sequence of instructions. The computer can then handle arrays of any length with a single program. Register indirect addressing is the key to the processing arrays since it allows you to vary the actual address of the data (the eective
Repeat Until
Initialisation Section
Algorithm 9.1a
Concluding Section
Initialisation Section
Algorithm 9.1b
task incomplete
While
Repeat
Processing Section
address )
autoincrementing mode is particularly convenient for processing arrays since it automatically updates the register for the next iteration. No additional instruction is necessary. You can even have an automatic increment by 2 or 4 if the array contains 16-bit or 32-bit data or addresses. Although our examples show the processing of arrays with autoincrementing (adding 1, 2, or 4 after each iteration), the procedure is equally valid with autodecrementing (subtracting 1, 2, or 4 before each iteration). Many programmers nd moving backward through an array somewhat awkward
71
72
CHAPTER 9.
PROGRAM LOOPS
and dicult to follow, but it is more ecient in many situations. The computer obviously does not know backward from forward. The programmer, however, must remember that the processor increments an address register after using it but decrements an address register before using it. This dierence aects initialisation as follows:
1. When moving forward through an array (autoincrementing), start the register pointing to the lowest address occupied by the array. 2. When moving backward through an array (autodecrementing), start the register pointing one step (1, 2, or 4) beyond the highest address occupied by the array.
9.1
Program Examples
sum16.s
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
Add a series of 16 bit numbers by using a table address look-up TTL AREA ENTRY Ch5Ex1 Program, CODE, READONLY
Main
Loop
LDR EOR LDR LDR ADD ADD SUBS BNE STR SWI AREA
R0, =Data1 R1, R1, R1 R2, Length R3, [R0] R1, R1, R3 R0, R0, #+4 R2, R2, #0x1 Loop R1, Result &11 Data1, DATA &2040 &1C22 &0242 0 Data2, DATA (TablEnd - Table) / 4 0
;load the address of the lookup table ;clear R1 to store sum ;init element count ;get the data ;add it to r1 ;increment pointer ;decrement count with zero set ;if zero flag is not set, loop ;otherwise done - store result
Table
DCW ALIGN DCW ALIGN DCW ALIGN TablEnd DCD Length Result AREA DCW ALIGN DCW END
;because we're having to align ;gives the loop count ;storage for result
Program 9.1b:
sum16b.s
9.1.
PROGRAM EXAMPLES
73
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
This example has nothing in the lookup table, and the program handles this TTL AREA ENTRY Ch5Ex2 Program, CODE, READONLY
Main
Loop
LDR EOR LDR CMP BEQ LDR ADD ADD SUBS BNE STR SWI AREA
R0, =Data1 R1, R1, R1 R2, Length R2, #0 Done R3, [R0] R1, R1, R3 R0, R0, #+4 R2, R2, #0x1 Loop R1, Result &11 Data1, DATA 0 Data2, DATA (TablEnd - Table) / 4 0
;load the address of the lookup table ;clear R1 to store sum ;init element count
Done
;get the data that R0 points to ;add it to r1 ;increment pointer ;decrement count with zero set ;if zero flag is not set, loop ;otherwise done - store result
Table TablEnd DCD Length Result AREA DCW ALIGN DCW END
;Table is empty
;because we're having to align ;gives the loop count ;storage for result
32-bit 64-bit
countneg.s
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
Scan a series of 32 bit numbers to find how many are negative TTL AREA ENTRY Ch5Ex3 Program, CODE, READONLY
Main
Loop
LDR EOR LDR CMP BEQ LDR CMP BPL ADD ADD SUBS
R0, =Data1 R1, R1, R1 R2, Length R2, #0 Done R3, [R0] R3, #0 Looptest R1, R1, #1 R0, R0, #+4 R2, R2, #0x1
;load the address of the lookup table ;clear R1 to store count ;init element count ;if table is empty ;get the data ;skip next line if +ve or zero ;increment -ve number count ;increment pointer ;decrement count with zero set
Looptest
74
CHAPTER 9.
PROGRAM LOOPS
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
Done
Loop R1, Result &11 Data1, DATA &F1522040 &7F611C22 &80000242 0 Data2, DATA (TablEnd - Table) / 4 0
;if zero flag is not set, loop ;otherwise done - store result
Table
DCD DCD DCD TablEnd DCD Length Result AREA DCW ALIGN DCW END
;because we're having to align ;gives the loop count ;storage for result
Program 9.2b:
countneg16.s
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
Scan a series of 16 bit numbers to find how many are negative TTL AREA ENTRY Ch5Ex4 Program, CODE, READONLY
Main
Loop
LDR EOR LDR CMP BEQ LDR AND CMP BEQ ADD ADD SUBS BNE STR SWI AREA
R0, =Data1 R1, R1, R1 R2, Length R2, #0 Done R3, [R0] R3, R3, #0x8000 R3, #0x8000 Looptest R1, R1, #1 R0, R0, #+4 R2, R2, #0x1 Loop R1, Result &11 Data1, DATA &F152 &7F61 &8000 0 Data2, DATA (TablEnd - Table) / 4 0
;load the address of the lookup table ;clear R1 to store count ;init element count ;if table is empty ;get the data ;bit wise AND to see if the 16th ;bit is 1 ;skip next line if zero ;increment -ve number count ;increment pointer ;decrement count with zero set ;if zero flag is not set, loop ;otherwise done - store result
Looptest
Done
Table
DCW ALIGN DCW ALIGN DCW ALIGN TablEnd DCD Length Result AREA DCW ALIGN DCW END
;because we're having to align ;gives the loop count ;storage for result
9.1.
PROGRAM EXAMPLES
75
largest16.s
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
Scan a series of 16 bit numbers to find the largest TTL AREA ENTRY Ch5Ex5 Program, CODE, READONLY
Main
Loop
LDR EOR LDR CMP BEQ LDR CMP BCC MOV ADD SUBS BNE STR SWI AREA
R0, =Data1 R1, R1, R1 R2, Length R2, #0 Done R3, [R0] R3, R1 Looptest R1, R3 R0, R0, #+4 R2, R2, #0x1 Loop R1, Result &11 Data1, DATA &A152 &7F61 &F123 &8000 0 Data2, DATA (TablEnd - Table) / 4 0
;load the address of the lookup table ;clear R1 to store largest ;init element count ;if table is empty ;get the data ;bit is 1 ;skip next line if zero ;increment -ve number count ;increment pointer ;decrement count with zero set ;if zero flag is not set, loop ;otherwise done - store result
Looptest
Done
Table
DCW ALIGN DCW ALIGN DCW ALIGN DCW ALIGN TablEnd DCD AREA Length Result DCW ALIGN DCW END
;because we're having to align ;gives the loop count ;storage for result
normalize.s
1 2 3 4 5 6 7 8 9
normalize a binary number TTL AREA ENTRY Ch5Ex6 Program, CODE, READONLY
Main
LDR EOR
76
CHAPTER 9.
PROGRAM LOOPS
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
Loop
LDR CMP BEQ ADD MOVS BPL STR STR SWI AREA
R3, [R0] R3, R1 Done R1, R1, #1 R3, R3, LSL#0x1 Loop R1, Shifted R3, Normal &11 Data1, DATA &30001000 &00000001 &00000000 &C1234567 Result, DATA Table 0 0
;get the data ;bit is 1 ;if table is empty ;increment pointer ;decrement count with zero set ;if negative flag is not set, loop ;otherwise done - store result
Done
Table * * *
9.2
Problems
carry over (or overow). Note: Checksums are often used to ensure that data has been correctly read. A checksum calculated when reading the data is compared to a checksum that is stored with the data. If the two checksums do not agree, the system will usually indicate an error, or automatically read the data again. Sample Problem:
Input:
LENGTH START
00000003 28 55 26
( (
Output:
CHECKSUM
28 + 55 + 26
= 00101000 (28) + 01010101 (55) = 01111101 (7D) + 00100110 (26) = 10100011 (A3)
Data Checksum
9.2.
PROBLEMS
77
NUMZERO
LENGTH and the starting series of numbers start with the START NUMNEG, the number of zero elements in of positive elements in variable NUMPOS.
Sample Problem:
Input:
LENGTH START
( ( ( ( ( ( ( ( ( (
Output:
2 1 3
Number of items Start of data table Positive Negative Positive Zero Negative Positive 2 negative numbers: 8D489867 and E605546C 1 zero value 3 positive numbers: 76028326, 21202549 and 00000004
) ) ) ) ) ) ) ) )
NUMMIN
LENGTH
START
variable.
Sample Problem:
Input:
LENGTH START
5 65 79 15 E3 72
( (
Output:
NUMMIN
15
NUMBITS
NUM,
variable.
Sample Problem:
Input: Output:
NUM NUMBITS
LENGTH
Store the value with the most bits set in the Sample Problem:
NUM
START
label.
78
CHAPTER 9.
PROGRAM LOOPS
Input:
LENGTH START
Number of items
(0010 0000 0101 1010 0001 0101 1101 0011 13) (0010 0101 0110 1100 1000 0111 0000 0000 11) (0010 1001 0101 0100 0110 1000 1111 0010 14) (0010 1001 1000 0101 0110 0111 0111 1001 16) (1001 0001 0100 0111 0101 1001 0010 1010 14) (
Output:
NUM
29856779
10
Strings
Microprocessors often handle data which represents printed characters rather than numeric quantities. Not only do keyboards, printers, communications devices, displays, and computer terminals expect or provide character-coded data, but many instruments, test systems, and controllers also require data in this form. ASCII (American Standard Code for Information Interchange) is the most commonly used code, but others exist. We use the standard seven-bit ASCII character codes, as shown in Table 10.1; the character code occupies the low-order seven bits of the byte, and the most signicant bit of the byte holds a 0 or a parity bit.
10.1
The codes for the numbers and letters form ordered sequences. Since the ASCII codes for
the characters 0 through 9 are 3016 through 3916 you can convert a decimal digit to the = ASCII 0. Since the codes for letters (41 16 through 5A16 and 6116 through 7A16 ) are in order, you can alphabetises strings by sorting them according to their numerical values. equivalent ASCII characters (and ASCII to decimal) by simple adding the ASCII oset: 30 16
The computer does not distinguish between printing and non-printing characters. Only the I/0 devices make that distinction. An ASCII I/0 device handles data only in ASCII. For example, if you want an ASCII printer
to print the digit 7, you must send it 37 16 as the data; 0716 will ring the bell. Similarly, tab key.
if a user presses the 9 key on an ASCII keyboard, the input data will be 39 16 ; 0916 is the
Many ASCII devices do not use the entire character set. For example, devices may ignore many control characters and may not print lower-case letters. Despite the denition of the control characters many devices interpret them dierently. For example they typically uses control characters in a special way to provide features such as cursor control on a display, and to allow software control of characteristics such as rate of data transmission, print width, and line length.
Some widely used ASCII control characters are: 0A16 0D16 0816 7F16 LF CR BS DEL line feed carriage return backspace rub out or delete character
79
80
CHAPTER 10.
STRINGS
LSB 0 1 2 3 4 5 6 7 8 9 A B C D E F
1 DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN EM SUB ESC FS GS RS US
2 SP
! " # $ % & ' ( ) * + , . /
MSB 3 4
0 1 2 3 4 5 6 7 8 9 : ; < = > ?
@ A B C D E F G H I J K L M N 0
P Q R S T U V W X Y Z [ \ ] ^ _
` a b c d e f g h i j k l m n o
DEL
p q r s t u v w x y z { | } ~
Control Characters Null DLE Data link escape Start of heading DC1 Device control 1 Start of text DC2 Device control 2 End of text DC3 Device control 3 End of tx DC4 Device control 4 Enquiry NAK Negative ack Acknowledge SYN Synchronous idle Bell, or alarm ETB End of tx block Backspace CAN Cancel Horizontal tab EM End of medium Line feed SUB Substitute Vertical tab ESC Escape Form feed FS File separator Carriage return GS Group separator Shift out RS Record separator Shift in US Unit separator Space DEL Delete
Each ASCII character occupies eight bits. This allows a large character set but is wasteful when only a few characters are actually being used. If, for example, the data consists entirely of decimal numbers, the ASCII format (allowing one digit per byte) requires twice as much storage, communications capacity, and processing time as the BCD format (allowing two digits per byte).
The assembler includes a feature to make character-coded data easy to handle, single quotation marks around a character indicate the character's ASCII value. For example,
MOV
is the same as
R3, #'A'
MOV
R3, #0x41
The rst form is preferable for several reasons. It increases the readability of the instruction, it also avoids errors that may result from looking up a value in a table. code has been designed for. The program does not depend on ASCII as the character set, since the assembler handles the conversion using whatever
10.2
A string of characters
In assembly programming it is normal to have
Individual characters on there own are not really all that helpful. As humans we need a string of characters in order to form meaningful text. to process one character at a time. program 10.1a is: However, the assembler does at least allow us to store a
DCB
DCB
"Hello, World", CR
10.2.
A STRING OF CHARACTERS
Binary: Text:
81
48 H
65 e
6C l
6C l
6F o
2C ,
20
SP
57 W
6F o
72 r
6C l
64 d
0D
CR
Use table 10.1 to check that this is correct. In order to make the program just that little bit more readable, line 5 denes the label
CR
There are three main methods for handling strings: Fixed Length, Terminated, and Counted. It is normal for a high level language to support just one method. use of Zero-Terminated strings, while
Pascal
and
Ada
C/C++
and
Java
to provide your own support for the alternative string type it is seldom done. A good programmer will use a mix of methods depending of the nature of the strings concerned.
nth
This advantage is however also a major disadvantage. For example a persons name can be anything from two characters to any number of characters. Although it would be possible to reserve sucient space for the longest of names this amount of memory would be required for all names, including the two letter ones. This is a signicant waist of memory. It would be possible to reserve just ten characters for each name. When a two letter name appears it would have to be padded out with spaces in order to make the name ten characters in length. When a name longer than ten characters appears it would have to be truncated down to just ten characters thus chopping o part of the name. This requires extra processing and is not entirely friendly to users who happen to have a long name. When there is little memory and all the strings are known in advance it may be a good idea to use xed length strings. For example, command driven systems tend to use a xed length strings for the list of commands.
sentinel.
C/C++.
The NUL character also has a good feeling about it, as it is represented by the value
0, has no other meaning and it is easier to detected than any other character. This is frequently referred to as a Null- or Zero-Terminated string or simply as an ASCIIZ string. The terminated string has the advantage that it can be of any length. Processing the string is fairly simply, you enter into a loop processing each character at a time until you reach the sentinel. The disadvantage is that the sentinel character can not appear in the string. This is another reason why the NUL character is such a good choice for the sentinel.
82
CHAPTER 10.
STRINGS
perceived complexity. Many people feel that the complexity of the counted string outweighs the
10.3
International Characters
As computing expands outside of the English speaking world we have to provide support for languages other than standard American. Many European languages use letters that are not available in standard ASCII, for example: , , , , , , , , , , and . This is particularly important when dealing with names: ngstrm, Karlstrae or ukasiewicz. The ASCII character set is not even capable of handling English correctly. When we borrow a word from another language we also use it's
diacritic marks
(or
accents ).
rather see pt on a menu rather than pate. ASCII does not provide support for such accents. To overcome this limitation the international community has produced a new character encoding,
known as Unicode. In Unicode the character code is two bytes long, the rst byte indicates which character set the character comes from, while the second byte indicates the character position within the character set. this new wide character. While Unicode is sucient to represent the characters from most modern languages, it is not sucient to represent all the written languages of the world, ancient and modern. Hence an extended version, known as Unicode-32 is being developed where the character set is a 23-bit value (three bytes). Unicode is a subset of Unicode-32, while ASCII is a subset of Unicode. Although we do not consider Unicode you should be aware of the problem of international character sets and the solution Unicode provides. The traditional ASCII character set is incorporated into Unicode as character set zero. In the revised
wchar
10.4
Program Examples
strlencr.s
10.4.
PROGRAM EXAMPLES
83
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
; Find the length of a CR terminated string TTL CR EQU AREA ENTRY Main Loop LDR EOR LDRB CMP BEQ ADD BAL STR SWI AREA Table DCB ALIGN Ch6Ex1 - strlencr 0x0D Program, CODE, READONLY
R0, =Data1 R1, R1, R1 R2, [R0], #1 R2, #CR Done R1, R1, #1 Loop R1, CharCount &11 Data1, DATA "Hello, World", CR Result, DATA 0
; Load the address of the lookup table ; Clear R1 to store count ; ; ; ; ; Load the first byte into R2 Is it the terminator ? Yes => Stop loop No => Increment count Read next char
Done
; Store result
Program 10.1b:
strlen.s
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
; Find the length of a null terminated string TTL AREA ENTRY Main Loop LDR MOV ADD LDRB CMP BNE STR SWI AREA Table DCB ALIGN Ch6Ex1 - strlen Program, CODE, READONLY
R0, =Data1 R1, #-1 R1, R1, #1 R2, [R0], #1 R2, #0 Loop R1, CharCount &11 Data1, DATA "Hello, World", 0 Result, DATA 0
; Load the address of the lookup table ; Start count at -1 ; ; ; ; Increment count Load the first byte into R2 Is it the terminator ? No => Next char
; Store result
84
CHAPTER 10.
STRINGS
skipblanks.s
Ch6Ex3
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
Blank
EQU AREA ENTRY ADR MOV LDRB CMP BEQ SUB STR SWI AREA
Main Loop
R0, Data1 R1, #Blank R2, [R0], #1 R2, R1 Loop R0, R0, #1 R0, Pointer &11 Data1, DATA " 7 "
;load the address of the lookup table ;store the blank char in R1 ;load the first byte into R2 ;is it a blank ;if so loop ;otherwise done - adjust pointer ;and store it
Table
DCB ALIGN
Result, DATA 0
padzeros.s
Ch6Ex4
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
Blank Zero
EQU EQU AREA ENTRY LDR MOV MOV LDRB CMP BNE
Main
Loop
R0, =Data1 R1, #Zero R3, #Blank R2, [R0], #1 R2, R1 Done
;load the address of the lookup table ;store the zero char in R1 ;and the blank char in R3 ;load the first byte into R2 ;is it a zero ;if not, done
10.4.
PROGRAM EXAMPLES
85
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
SUB STRB ADD BAL Done SWI AREA Table DCB ALIGN
R0, R0, #1 R3, [R0] R0, R0, #1 Loop &11 Data1, DATA "000007000" Result, DATA 0
;otherwise adjust the pointer ;and store it blank char there ;otherwise adjust the pointer ;and loop ;all done
string in Result
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
setparity.s
; Set the parity bit on a series of characters store the amended string in Result TTL AREA ENTRY Main LDR LDR LDRB CMP BEQ LDRB MOV MOV MOV MOV MOVS BPL ADD SUBS BNE TST BEQ ORR STRB BAL STRB SUBS BNE SWI Ch6Ex5 Program, CODE, READONLY
MainLoop
R0, =Data1 R5, =Pointer R1, [R0], #1 R1, #0 Done R2, R6, R2, R3, R4, [R0], #1 R2 R2, LSL #24 #0 #7
;load the address of the lookup table ;store the string length in R1 ;nothing to do if zero length ;load the first byte into R2 ;keep a copy of the original char ;shift so that we are dealing with msb ;zero the bit counter ;init the shift counter ;left shift ;if msb is not a one bit, branch ;otherwise add to bit count ;update shift count ;loop if still bits to check ;is the parity even ;if so branch ;otherwise set the parity bit ;and store the amended char ;store the unamended char if even pty ;decrement the character count
ParLoop
DontAdd
R2, R2, LSL #1 DontAdd R3, R3, #1 R4, R4, #1 ParLoop R3, #1 Even R6, R6, #0x80 R6, [R5], #1 Check R6, [R5], #1 R1, R1, #1 MainLoop &11
86
CHAPTER 10.
STRINGS
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
Data1, DATA 6 0x31 0x32 0x33 0x34 0x35 0x36 Result, DATA 0 ;storage for parity characters ;data table starts with byte length of string ;the string
cstrcmp.s
Ch6Ex6
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
Main
R0, =Data1 R1, =Data2 R2, Match R3, [R0], #4 R4, [R1], #4 R3, R4 Done R3, #0 Same
;load the address of the lookup table ;assume strings not equal - set to -1 ;store the first string length in R3 ;store the second string length in R4 ;if they are different lengths, ;they can't be equal ;test for zero length if both are ;zero length, nothing else to do
* Loop
if we got this far, we now need to check the string char by char LDRB LDRB CMP BNE SUBS BEQ B R5, [R0], #1 R6, [R1], #1 R5, R6 Done R3, R3, #1 Same Loop R2, #0 R2, Match &11 Data1, DATA 3 "CAT" Data2, DATA 3 "CAT" Result, DATA ;character of first string ;character of second string ;are they the same ;if not the strings are different ;use the string length as a counter ;if we got to the end of the count ;the strings are the same ;not done, loop ;clear the -1 from match (0 = match) ;store the result
Same Done
MOV STR SWI AREA DCD DCB AREA DCD DCB AREA
Table1
;data table starts with byte length of string ;the string ;data table starts with byte length of string ;the string
Table2
10.4.
PROGRAM EXAMPLES
87
44 45 46 47
Match
&FFFF
Program 10.5b:
strcmp.s Compare null terminated strings for equality assume that we have no knowledge of the data structure so we must assess the individual strings
; Compare two null terminated strings for equality TTL AREA ENTRY Main LDR LDR LDR MOV MOV LDRB CMP BEQ ADD BAL LDRB CMP BEQ ADD BAL CMP BNE CMP BEQ LDR LDR * Loop Ch6Ex7 Program, CODE, READONLY
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
Count1
;load the address of the lookup table ;assume strings not equal, set to -1 ;init register ;load the first byte into R5 ;is it the terminator ;if not, Loop ;increment count ;load the first byte into R5 ;is it the terminator ;if not, Loop ;increment count
Count2
R5, [R0], #1 R5, #0 Count2 R3, R3, #1 Count1 R5, [R1], #1 R5, #0 Next R4, R4, #1 Count2 R3, R4 Done R3, #0 Same R0, =Data1 R1, =Data2
Next
;if they are different lengths, ;they can't be equal ;test for zero length if both are ;zero length, nothing else to do ;need to reset the lookup table
if we got this far, we now need to check the string char by char LDRB LDRB CMP BNE SUBS BEQ BAL R5, [R0], #1 R6, [R1], #1 R5, R6 Done R3, R3, #1 Same Loop R2, #0 R2, Match &11 Data1, DATA "Hello, World", 0 Data2, DATA "Hello, worl", 0 ;character of first string ;character of second string ;are they the same ;if not the strings are different ;use the string length as a counter ;if we got to the end of the count ;the strings are the same ;not done, loop ;clear the -1 from match (0 = match) ;store the result
Same Done
Table1
;the string
Table2
;the string
88
CHAPTER 10.
STRINGS
59 60 61 62 63
Match
10.5
Problems
START
ETX
STX
(End of Text) character (03 16 ). Save the length of the message, the
LENGTH
STX
and the
ETX
variable.
Sample Problem:
Input:
START
String
LENGTH
String
02 47 4F 03
) )
(ETX (GO)
Output:
02
START
variable and the string ends with a carriage return character ( 0D16 ).
Place the address of the last non-blank character in the Sample Problems:
POINTER
variable.
Input:
START
String
String
Test A
String
Test B
37 ( 7) 0D (CR)
Output:
POINTER
First Char
Fourth Char
START
variable
and the string is assumed to consist entirely of ASCII-coded decimal digits and a possible decimal
LENGTH variable.
in the string, assume that the decimal point is at the far right.
10.5.
PROBLEMS
89
Sample Problems:
Input:
START LENGTH
String
4
Test A
String
3
Test B
String
Output:
2E ( .)
37 ( 7) 31 ( 1)
36 ( 6)
Note that in the second case (Test B) the output is unchaged, as the number is assumed to be 671..
START
variable. The rst word of the string is its length which is followed by the string itself.
If the parity of all the characters in the string are correct, clear the place all ones (FFFFFFFF 16 ) into the variable. Sample Problems:
PARITY
variable; otherwise
Input:
START
String
PARITY
String
3
Test A
String
03
Test B
Output:
00000000 (True)
START1
START1
and
LENGTH variable. The START2 variables. If the string dened clear the GREATER variable; otherwise set
Input:
Test A
Test B
Test C
String1 String2
Output:
String1 String2
43 ( C) 41 ( A) 54 ( T) 42 ( B) 41 ( A) 54 ( T)
String1 String2
43 ( C) 41 ( A) 54 ( T) 52 ( C) 41 ( A) 54 ( T) 00000000 (CAT
String1 String2
43 ( C) 41 ( A) 54 ( T) 52 ( C) 55 ( U) 54 ( T) FFFFFFFF (CAT
GREATER
00000000 (CAT
>
BAT)
CAT)
<
CUT)
90
CHAPTER 10.
STRINGS
11
Code Conversion
Code conversion is a continual problem in microcomputer applications. Peripherals provide data in ASCII, BCD or various special codes. The microcomputer must convert the data into some standard form for processing. Output devices may require data in ASCII, BCD, seven-segment or other codes. Therefore, the microcomputer must convert the results to the proper form after it completes the processing. There are several ways to approach code conversion: 1. Some conversions can easily be handled by algorithms involving arithmetic or logical functions. The program may, however, have to handle special cases separately. 2. More complex conversions can be handled with lookup tables. requires little programming and is easy to apply. amount of memory if the range of input values is large. 3. Hardware is readily available for some conversion tasks. Typical examples are decoders The lookup table method
for BCD to seven-segment conversion and Universal Asynchronous Receiver/Transmitters (UARTs) for conversion between parallel and serial formats. In most applications, the program should do as much as possible of the code conversion work. Most code conversions are easy to program and require little execution time.
11.1
Program Examples
nibtohex.s
Ch7Ex1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
convert a single hex digit to its ASCII equivalent TTL AREA ENTRY
Main
R0, Digit R1, =Result R0, #0xA Add_0 R0, R0, #"A"-"0"-0xA R0, R0, #"0" R0, [R1] &11
;load the digit ;load the address for the result ;is the number < 10 decimal ;then branch ;add offset for 'A' to 'F' ;convert to ASCII ;store the result
Add_0
91
92
CHAPTER 11.
CODE CONVERSION
19 20 21 22 23 24 25 26 27
Digit
Data1, DATA &0C Data2, DATA 0 ;the hex digit ;storage for result
Result
Program 11.1b:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
now something a little more adventurous - convert a 32 bit hexadecimal number to an ASCII string and output to the terminal TTL AREA ENTRY EQU LDR MOV MOV MOV MOV SUB AND CMP BLT ADD Ch7Ex2 Program, CODE, READONLY 0x0000000F R1, Digit R4, #8 R5, #28 R3, R1 R3, R3, LSR R5 R5, R5, #4 R3, R3, #Mask R3, #0xA Add_0 R3, R3, #"A"-"0"-0xA R3, R3, #"0" R0, R3 &0 R4, R4, #1 MainLoop R0, #&0D &0 &11 Data1, DATA &DEADBEEF ;load the digit ;init counter ;control right shift ;copy original word ;right shift the correct number of bits ;reduce the bit shift ;mask out all but the ls nibble ;is the number < 10 decimal ;then branch ;add offset for 'A' to 'F' ;convert to ASCII ;prepare to output ;output to console ;decrement counter ;add a CR character ;output it ;all done ;the hex word
Mask start
MainLoop
Add_0
Digit
nibtoseg.s
Ch7Ex3
1 2 3 4 5 6
11.1.
PROGRAM EXAMPLES
93
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
Main
LDR EOR LDRB CMP BHI ADD LDRB STR SWI AREA DCB DCB DCB DCB DCB DCB DCB DCB DCB DCB ALIGN AREA DCB ALIGN AREA DCD END
R0, =Data1 R1, R1, R1 R2, Digit R2, #9 Done R0, R0, R2 R1, [R0] R1, Result &11 Data1, DATA &3F &06 &5B &4F &66 &6D &7D &07 &7F &6F Data2, DATA &05 Data3, DATA 0
;load the start address of the table ;clear register for the code ;get the digit to encode ;is it a valid digit? ;clear the result ;advance the pointer ;and get the next byte ;store the result ;all done ;the binary conversions table
Done
Table
Digit
Result
dectonib.s
Ch7Ex4
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
Main
Done
MOV LDRB SUBS BCC CMP BHI MOV STR SWI AREA DCB ALIGN
R1, #-1 R0, Char R0, R0, #"0" Done R0, #9 Done R1, R0 R1, Result &11 Data1, DATA &37
;set -1 as error flag ;get the character ;convert and check if character is < 0 ;if so do nothing ;check if character is > 9 ;if so do nothing ;otherwise.... ;.....store the decimal no ;all done ;ASCII representation of 7
Char
94
CHAPTER 11.
CODE CONVERSION
24 25 26 27
Result
Data2, DATA 0
ubcdtohalf.s
Ch7Ex5
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
Main
LDR MOV MOV MOV ADD MOV MOV ADD LDRB ADD SUBS BNE STR SWI
;load address of BCD number ;init counter ;clear result register ;and final register ;multiply by 2 ;mult by 8 (2 x 4) ;= mult by 10 ;load digit and incr address ;add the next digit ;decr counter ;if counter != 0, loop ;store the result ;all done ;an unpacked BCD number
Loop
R4, [R0], #1 R1, R1, R4 R5, R5, #1 Loop R1, Result &11 Data1, DATA &02,&09,&07,&01 Data2, DATA 0
BCDNum
Result
Program 11.4b:
ubcdtohalf2.s
Ch7Ex6
1 2 3 4 5 6 7 8 9 10 11 12 13 14
convert an unpacked BCD number to binary using MUL TTL AREA ENTRY
Main
=BCDNum #4 #0 #0 #10
;load address of BCD number ;init counter ;clear result register ;and final register ;multiplication constant
11.1.
PROGRAM EXAMPLES
95
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
Loop
R6, R1 R1, R6, R7 R4, [R0], #1 R1, R1, R4 R5, R5, #1 Loop R1, Result &11 Data1, DATA &02,&09,&07,&01 Data2, DATA 0
;mult by 10 ;load digit and incr address ;add the next digit ;decr counter ;if count != 0, loop ;store the result ;all done ;an unpacked BCD number
BCDNum
Result
halftobin.s
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
store a 16bit binary number as an ASCII string of '0's and '1's TTL AREA ENTRY Ch7Ex7 Program, CODE, READONLY
Main
LDR ADD LDRB MOV MOV LDR MOVS BCS STRB BAL STRB SUBS BNE SWI
;load startr address of string ;adjust for length of string ;init counter ;load character '1' to register ;load the number to process ;rotate right with carry ;if carry set branch (LSB was a '1' bit) ;otherwise store "0" ;and branch to counter code ;store a "1" ;decrement counter ;loop while not 0
Loop
Loopend Decr
R1, R1, ROR #1 Loopend R3, [R0], #-1 Decr R2, [R0], #-1 R6, R6, #1 Loop &11 Data1, DATA &31D2 Data2, DATA 16
Number
String
96
CHAPTER 11.
CODE CONVERSION
0 1 2 3 4 5 6 7 8 9 A B C D E F
3F 06 5B 4F 66 6D 7D 07 7F 6F 77 7C 3A 5E 7A 71
7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
6 g 0 0 1 1 1 1 1 0 1 1 1 1 0 1 1 1
5 f 1 0 0 0 1 1 1 0 1 1 1 1 1 0 1 1
4 e 1 0 1 0 0 0 1 0 1 0 1 1 1 1 1 1
3 d 1 0 1 1 0 1 1 0 1 1 0 1 1 1 1 0
2 c 1 1 0 1 1 1 1 1 1 1 1 1 0 1 0 0
1 b 1 1 1 1 1 0 0 1 1 1 1 0 0 1 0 0
0 a 1 0 1 1 0 1 1 1 1 1 1 0 1 0 1 1
a f e g d b c
11.2
Problems
A_DIGIT variable from an ASCII character to a hexadecimal digit and H_DIGIT variable. Assume that A_DIGIT contains the ASCII representation
Input: Output:
A_DIGIT H_DIGIT
43 ( C) 0C
Test A
36 ( 6) 06
Test B
NUMBER
CODE variable from a seven-segment code to a decimal number and NUMBER variable. If CODE does not contain a valid seven-segment code, set
to FF16 . Use the seven-segment table given in Figure 11.1 and try to match codes.
Sample Problems:
Input: Output:
CODE NUMBER
Test A 4F 03
Test B 28 FF
CHAR
CHAR.
DIGIT
If the number in
DIGIT
Sample Problems:
Input: Output:
DIGIT CHAR
Test A 07 37 (7)
Test B 55 20 (Space)
11.2.
PROBLEMS
97
NUMBER
NUMBER STRING
The 32-bit
Sample Problem:
Input: Output: 1C52 07 02 05 00 (7250 10 ) (7) (2) (5) (0)
NUMBER
BCDNUM
variable.
Sample Problem:
Input: Output:
BCDNUM NUMBER
STRING to an 8-bit binary number in the NUMBER. Clear the byte variable ERROR if all the ASCII characters are either ASCII 1 or 0; otherwise set ERROR to all ones (FF16 ).
Test A 31 31 30 31 30 30 31 30 (1) (1) (0) (1) (0) (0) (1) (0) (1101 0010) ( ) 31 31 30 31 30 37 31 30 00 FF Test B (1) (1) (0) (1) (0) (7) (1) (0) ( (
Sample Problems:
Input:
STRING
Output:
NUMBER ERROR
D2 0
No Error
Valid Error
) )
98
CHAPTER 11.
CODE CONVERSION
12
Arithmetic
Much of the arithmetic in some microprocessor applications consists of multiple-word binary or decimal manipulations. sequences of instruction. Most processors provide for both signed and unsigned binary arithmetic. are the same whether the numbers are signed or unsigned. Multiple-precision binary arithmetic requires simple repetitions of the basic instructions. The Signed numbers are The processor provides for decimal addition and subtraction, but does not provide for decimal multiplication or division, you must implement these operations with
represented in two's complement form. This means that the operations of addition and subtraction
Carry ag transfers information between words. It is set when an addition results in a carry or a subtraction results in a borrow. Add with Carry and Subtract with Carry use this information from the previous arithmetic operation. Decimal arithmetic is a common enough task for microprocessors that most have special instructions for this purpose. These instructions may either perform decimal operations directly or correct the results of binary operations to the proper decimal form. terminals. You can implement decimal multiplication and division as series of additions and subtractions, respectively. Extra storage must be reserved for results, since a multiplication produces a result twice as long as the operands. A division contracts the length of the result. Multiplications and divisions are time-consuming when done in software because of the repeated operations that are necessary. Decimal arithmetic is essential in such applications as point-of-sale terminals, check processors, order entry systems, and banking
12.1
Program Examples
add64.s
64 Bit Addition
1 2 3 4 5 6 7 8 9 10 11 12 13 14
64 bit addition TTL AREA ENTRY 64 bit addition Program, CODE, READONLY
Main
; ; ; ; ; ; ;
Pointer to first value Load first part of value1 Load lower part of value1 Pointer to second value Load upper part of value2 Load lower part of value2 Add lower 4 bytes and set carry flag
99
100
CHAPTER 12.
ARITHMETIC
15 16 17 18 19 20 21 22 23 24 25
ADC LDR STR STR SWI Value1 Value2 Result DCD DCD DCD END
R5, R1, R3 R0, =Result R5, [R0] R6, [R0, #4] &11 &12A2E640, &F2100123 &001019BF, &40023F51 0
; Add upper 4 bytes including carry ; Pointer to Result ; Store upper part of result ; Store lower part of result ; Value to be added ; Value to be added ; Space to store result
addbcd.s
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
add two packed BCD numbers to give a packed BCD result TTL AREA ENTRY Ch8Ex3 Program, CODE, READONLY 0x0000000F R0, R1, R2, R8, R0, R5, =Result BCDNum1 BCDNum2 Length R0, #3 #0 ;address for storage ;load the first BCD number ;and the second ;init counter ;adjust for offset ;carry ;copy what is left in the data register ;and the other number ;mask out everything except low order nibble ;mask out everything except low order nibble ;shift the original number one nibble ;shift the original number one nibble ;add the digits ;and the carry ;is it over 10? ;if not, reset the carry to 0 ;otherwise set the carry ;and subtract 10 ;carry reset to 0 ;copy what is left in the data register ;and the other number ;mask out everything except low order nibble ;mask out everything except low order nibble ;shift the original number one nibble ;shift the original number one nibble ;add the digits ;and the carry ;is it over 10? ;if not, reset the carry to 0 ;otherwise set the carry ;and subtract 10
Mask Main
EQU LDR LDR LDR LDRB ADD MOV MOV MOV AND AND MOV MOV ADD ADD CMP BLT MOV SUB B MOV MOV MOV AND AND MOV MOV ADD ADD CMP BLT MOV SUB B
Loop
RCarry1 Next
R3, R1 R4, R2 R3, R3, #Mask R4, R4, #Mask R1, R1, LSR #4 R2, R2, LSR #4 R6, R3, R4 R6, R6, R5 R6, #0xA RCarry1 R5, #1 R6, R6, #0xA Next R5, #0 R3, R1 R4, R2 R3, R3, #Mask R4, R4, #Mask R1, R1, LSR #4 R2, R2, LSR #4 R7, R3, R4 R7, R7, R5 R7, #0xA RCarry2 R5, #1 R7, R7, #0xA Loopend
12.1.
PROGRAM EXAMPLES
101
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
RCarry2 Loopend
R5, #0 R7, R7, LSL #4 R6, R6, R7 R6, [R0], #-1 R8, R8, #1 Loop &11 Data1, DATA &04 &36, &70, &19, &85 Data2, DATA &12, &66, &34, &59 Data3, DATA 0
;carry reset to 0 ;shift the second digit processed to the left ;and OR in the first digit to the ls nibble ;store the byte, and decrement address ;decrement loop counter ;loop while > 0
AREA DCB ALIGN BCDNum1 DCB Length AREA BCDNum2 DCB Result AREA DCD END
;an 8 digit packed BCD number ;another 8 digit packed BCD number ;storage for result
12.1.4 Multiplication
16-Bit
Program 12.4a:
mul16.s
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
16 bit binary multiplication TTL AREA ENTRY Ch8Ex1 Program, CODE, READONLY
Main
;load first number ;and second ;x:= y * x ;won't work - not allowed ;all done ;a 16 bit binary number ;another
AREA Number1 DCD Number2 DCD ALIGN Result AREA DCD ALIGN END
32-Bit
Program 12.4b:
mul32.s
102
CHAPTER 12.
ARITHMETIC
R1)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
* *
multiply two 32 bit number to give a 64 bit result (corrupts R0 and R1) TTL AREA ENTRY Ch8Ex4 Program, CODE, READONLY
Main
LDR LDR LDR MOV MOV BIC BIC MUL MUL MUL MUL ADDS ADDCS ADDS ADC STR ADD STR SWI
R0, R1, R6, R5, R3, R0, R1, R2, R0, R1, R3, R0, R3, R2, R3,
Number1 Number2 =Result R0, LSR #16 R1, LSR #16 R0, R5, LSL R1, R3, LSL R0, R1 R3, R0 R5, R1 R5, R3 R1, R0 R3, #&10000 R2, R0, LSL R3, R0, LSR
#16 #16
#16 #16
;load first number ;and second ;load the address of result ;top half of R0 ;top half of R1 ;bottom half of R0 ;bottom half of R1 ;partial result ;partial result ;partial result ;partial result ;add middle parts ;add in any carry from above ;LSB 32 bits ;MSB 32 bits ;store LSB ;increment pointer ;store MSB ;all done ;a 16 bit binary number ;another
R2, [R6] R6, R6, #4 R3, [R6] &11 Data1, DATA &12345678 &ABCDEF01 Data2, DATA 0
AREA Number1 DCD Number2 DCD ALIGN Result AREA DCD ALIGN END
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
* * *
divide a 32 bit binary no by a 16 bit binary no store the quotient and remainder there is no 'DIV' instruction in ARM! TTL AREA ENTRY Ch8Ex2 Program, CODE, READONLY
Main
Loop
;load first number ;and second ;clear register for quotient ;test for divide by 0 ;is the divisor less than the dividend? ;if so, finished
12.2.
PROBLEMS
103
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
Err Done
R3, R3, #1 R0, R0, R1 Loop R3, #0xFFFFFFFF R0, Remain R3, Quotient &11 Data1, DATA &0075CBB1 &0141 Data2, DATA 0 0
;add one to quotient ;take away the number you first thought of ;and loop ;error flag (-1) ;store the remainder ;and the quotient ;all done ;a 16 bit binary number ;another
AREA Number1 DCD Number2 DCD ALIGN AREA Quotient DCD Remain DCD ALIGN END
12.2
Problems
LENGTH variable. The numbers themselves are stored NUM1 and NUM2 respectively. Subtract the number dierence in NUM1.
Sample Problem:
Input:
NUM2
NUM1.
Store the
LENGTH NUM1
( (
Number of words in each number First number is The second number is Dierence is
2F5B856884C32546706C9567 16 )
NUM2
14DF409885B81095A3BC1284 16 )
Output:
NUM1
1A7C44CFFF0B14B0CCB082E3 16 )
14DF409885B81095A3BC1284 1A7C44CFFF0B14B0CCB082E3
LENGTH.
NUM1.
NUM2
104
CHAPTER 12.
ARITHMETIC
Sample Problem:
Input:
LENGTH NUM1
4 36 70 19 85 78 34
( (
Number of bytes in each number The rst number is The second number is Dierence is
367019857834 10 )
NUM2
12 66 34 59 32 69
126634593269 10 )
Output:
NUM1
24 03 85 26 45 65
240385264565 10 )
That is,
367019857834
126634593269 240385264565
NUM1
instruction and place the result in the 64-bit variable Sample Problem:
Input:
PROD1.
NUM2
MULU
NUM1 NUM2
2468AC 16 )
3281088 10 )
Output:
PROD1
(MULU
72ECB8C25B60 16 )
PROD2
Shift product is
72ECB8C25B60 16 )
13
Tables and lists are two of the basic data structures used with all computers. We have already seen tables used to perform code conversions and arithmetic. Tables may also be used to identify or respond to commands and instructions, provide access to les or records, dene the meaning of keys or switches, and choose among alternate programs. Lists are usually less structured than tables. Lists may record tasks that the processor must perform, messages or data that the processor must record, or conditions that have changed or should be monitored.
13.1
Program Examples
match found
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
insert.s
* *
examine a table for a match - store a new entry at the end if no match found TTL AREA ENTRY Ch9Ex1 Program, CODE, READONLY
Main
Loop
LDR LDR LDR LDR LDR CMP BEQ SUBS LDR BNE SUB ADD STR STR
the start address of the list the new item the list counter counter and increment pointer
R1, R4 Done R2, R2, #1 R4, [R0], #4 Loop R0, R3, R3, R1, &11 Data1, DATA &4 &5376 &7615 &138A &21DC &20 R0, #4 R3, #1 Start [R0]
;does the item match the list? ;found it - finished ;no - get the next item ;get the next item ;and loop ;adjust the pointer ;increment the number of items ;and store it back ;store the new item at the end of the list
Done Start
Store
106
CHAPTER 13.
35 36 37 38 39 40
Program 13.1b:
extends insert.s
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
insert2.s
* *
examine a table for a match - store a new entry if no match found extends Ch9Ex1 TTL AREA ENTRY Ch9Ex2 Program, CODE, READONLY
Main
Loop
LDR LDR LDR LDR CMP BEQ LDR CMP BEQ SUBS LDR BNE SUB ADD STR STR SWI AREA DCD DCD DCD DCD DCD %
R0, List R1, NewItem R3, [R0] R2, [R0], #4 R3, #0 Insert R4, [R0], #4 R1, R4 Done R2, R2, #1 R4, [R0], #4 Loop R0, R3, R3, R1, &11 Data1, DATA &4 &5376 &7615 &138A &21DC &20 Data2, DATA &16FA Start R0, #4 R3, #1 Start [R0]
;load the start address of the list ;load the new item ;copy the list counter ;init counter and increment pointer ;it's an empty list ;so store it ;not empty - move to 1st item ;does the item match the list? ;found it - finished ;no - get the next item ;get the next item ;and loop ;adjust the pointer ;incr list count ;and store it ;store new item at the end ;all done ;length of list ;items
Insert
Done Start
Store
search.s
1 2 3 4
examine an ordered table for a match TTL AREA Ch9Ex3 Program, CODE, READONLY
13.1.
PROGRAM EXAMPLES
107
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
ENTRY Main LDR SUB LDR LDR CMP BEQ LDR CMP BEQ BHI SUBS LDR BNE R0, =NewItem R0, R0, #4 R1, NewItem R3, Start R3, #0 Missing R4, [R0], #-4 R1, R4 Done Missing R3, R3, #1 R4, [R0], #-4 Loop R3, #0xFFFFFFFF R3, Index &11 Data1, DATA &4 &0000138A &000A21DC &001F5376 &09018613 Data2, DATA &001F5376 0 Start ;load the address past the list ;adjust pointer to point at last element of list ;load the item to test ;init counter by reading index from list ;are there zero items ;zero items in list - error condition ;does the item match the list? ;found it - finished ;if the one to test is higher, it's not in the list ;no - decr counter ;get the next item ;and loop ;if we get to here, it's not there either ;flag it as missing ;store the index (either index or -1) ;all done ;length of list ;items
Loop
Missing MOV Done STR SWI AREA DCD DCD DCD DCD DCD
Start
head.s
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
remove the first element of a queue TTL AREA ENTRY Ch9Ex4 Program, CODE, READONLY
Main
R0, Queue R1, Pointer R0, #0 Done R1, [R0] R1, Queue &11 Data1, DATA Item1 0 20
;load the head of the queue ;and save it in 'Pointer' ;is it NULL? ;if so, nothing to do ;otherwise get the ptr to next ;and make it the start of the queue
Done
SWI
;pointer to the start of the queue ;space to save the pointer ;space for new entries
108
CHAPTER 13.
23 24 25 26 27 28 29 30 31 32 33 34
* each item consists of a pointer to the next item, and some data Item1 DCD Item2 ;pointer DCB 30, 20 ;data Item2 Item3 DCD DCB DCD DCB END Item3 30, 0xFF 0 30,&87,&65 ;pointer ;data ;pointer (NULL) ;data
sort.s
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
sort a list of values - simple bubble sort TTL AREA ENTRY Ch9Ex5 Program, CODE, READONLY
Main
Sort
LDR MOV LDRB MOV ADD MOV ADD LDRB LDRB CMP BCC STRB STRB ADD SUB CMP BHI CMP BNE SWI AREA DCB DCB AREA DCD END
List #0 [R6] R6
;pointer to start of list ;clear register ;get the length of list ;make a copy of start of list ;get address of last element ;zero flag for changes ;move 1 byte up the list each ;iteration ;load the first byte ;and the second ;compare them ;branch if r2 less than r3 ;otherwise swap the bytes ;like this ;flag that changes made ;decrement address to check ;have we checked enough bytes? ;if not, do inner loop ;did we mke changes ;if so check again - outer loop ;all done
Next
R7, R6, R0 R1, #0 R8, R8, #1 R2, [R7], #-1 R3, [R7] R2, R3 NoSwitch R2, R3, R1, R7, [R7], #1 [R7] R1, #1 R7, #1
NoSwitch
Done Start
Data1, DATA 6 &2A, &5B, &60, &3F, &D1, &19 Data2, DATA Start
List
13.2.
PROBLEMS
109
LIST
ITEM
variable. The rst entry in the list is the number (in words) of elements remaining in
the list. Move entries below the one removed up one position and reduce the length of the list by
ITEM LIST
Table
Table
D010257
Table
D0102596
C1212546
LIST
ITEM
variable. The rst entry in the list is the list's length in words. The list
itself consists of unsigned binary numbers in increasing order. Place the new entry in the correct position in the list, adjust the element below it down, and increase the length of the list by one. Sample Problems
Test A Input Output Input 7A35B310 Test B Output
ITEM LIST
Table
Table
7A35B310
09250037 29567322
0005
Table
next )
where
ITEM to a queue. The address of the rst element in the queue is QUEUE. Each element in the queue contains a structure of two items ( value and next is either the address of the next element in the queue or zero if there is no next
was
at the end of the queue. The
element. The new element is placed at the end (tail) of the queue; the new element's address will be in the element that
next
zero to indicate that it is now the end of the queue. Sample Problem:
110
CHAPTER 13.
ITEM QUEUE
Value
Input
00000000
Value
Output
item3 00000000
LIST.
LENGTH.
Sample Problem:
Input Output
LENGTH LIST
INDEX TABLE
Proc2,
14
The Stack
111
112
CHAPTER 14.
THE STACK
15
Subroutines
None of the examples that we have shown thus far is a typical program that would stand by itself. Most real programs perform a series of tasks, many of which may be used a number of times or be common to other programs. The standard method of producing programs which can be used in this manner is to write subroutines that perform particular tasks. The resulting sequences of instructions can be written once, tested once, and then used repeatedly. There are special instructions for transferring control to subroutines and restoring control to the main program. We often refer to the special instruction that transfers control to a subroutine as Call, Jump, or Brach to a Subroutine. The special instruction that restores control to the main program is usually called Return. In the ARM the Branch-and-Link instruction ( BL) is used to Branch to a Subroutine. current value of the program counter (
starting address of the subroutine in the program counter. The ARM does not have a standard Return from Subroutine instruction like other processors, rather the programmer should copy the value in the Link Register into the Program Counter in order to return to the instruction after the Branch-and-Link instruction. Thus, to return from a subroutine you should the instruction:
PC
or
R15
LR
or
R14
MOV
before calling the nested subroutine.
PC, LR
Should the subroutine wish to call another subroutine it will have to save the value of the Link Register
15.1
Types of Subroutines
The code can be placed anywhere in memory. You can use such a subroutine easily, regardless of other programs or the arrangement of the memory. A relocating loader is necessary to place the program in memory properly; the loader will start the program after other programs and will add the starting address or relocation constant to all addresses in the program.
Position Independent
The code does not require a relocating loader all program addresses are expressed relative to the program counter's current value. Data addresses are held in-registers at all times. We will discuss the writing of position independent code later in this chapter.
Reentrant
The subroutine can be interrupted and called by the interrupting program, giving the correct results for both the interrupting and interrupted programs. Reentrant subroutines are required for good for event based systems such as a multitasking operating system (Windows or Unix) and embedded real time environments. It is not dicult to make a subroutine reentrant. The only requirement is that the subroutine uses just registers and the stack for its data storage, and the subroutine is self contained in that it does not use any value dened outside of the routine (global values).
Recursive
The subroutine can call itself. Such a subroutine clearly must also be reentrant.
113
114
CHAPTER 15.
SUBROUTINES
15.2
Subroutine Documentation
Most programs consist of a main program and several subroutines. This is useful as you can use known prewritten routines when available and you can debug and test the other subroutines properly and remember their exact eects on registers and memory locations. You should provide sucient documentation such that users need not examine the subroutine's internal structure. Among necessary specications are:
A description of the purpose of the subroutine A list of input and output parameters Registers and memory locations used A sample case, perhaps including a sample calling sequence
15.3
In order to be really useful, a subroutine must be general. For example, a subroutine that can perform only a specialized task, such as looking for a particular letter in an input string of xed length, will not be very useful. If, on the other hand, the subroutine can look for any letter, in strings of any length, it will be far more helpful. In order to provide subroutines with this exibility, it is necessary to provide them with the ability to receive various kinds of information. We call data or addresses that we provide the subroutine parameters. An important part of writing subroutines is providing for transferring the parameters to the subroutine. This process is called Parameter Passing. There are three general approaches to passing parameters: 1. Place the parameters in registers. 2. Place the parameters in a block of memory. 3. Transfer the parameters and results on the hardware stack. The registers often provide a fast, convenient way of passing parameters and returning results. often results in unforeseen side eects; and it lacks generality. The trade-o here is between fast execution time and a more general approach. Such a trade-o is common in computer applications at all levels. General approaches are easy to learn and consistent; they can be automated through the use of macros. On the other hand, approaches that take advantage of the specic features of a particular task require less time and memory. The choice of one approach over the other depends on your application, but you should take the general approach (saving programming time and simplifying documentation and maintenance) unless time or memory constraints force you to do otherwise. The
limitations of this method are that it cannot be expanded beyond the number of available registers; it
R1
and
R2
; ; ; ;
R0
Length of Buffer in R0 Buffer A beginning address in R1 Buffer B beginning address in R2 Call subroutine
15.3.
115
Using this method of parameter passing, the subroutine can simply assume that the parameters are there. Results can also be returned in registers, or the addresses of locations for results can be passed as parameters via the registers. Of course, this technique is limited by the number of registers available. Processor features such as register indirect addressing, indexed addressing, and the ability to use any register as a stack pointer allow far more powerful and general ways of passing parameters.
LDR BL
If you place the parameter block immediately after the subroutine call the address of the parameter block is automatically place into the Link Register by the Branch and Link instruction. The subroutine must modify the return address in the Link Register in addition to fetching the parameters. Using this technique, our example would be modied as follows:
The subroutine saves' prior contents of CPU registers, then loads parameters and adjusts the return address as follows:
Subr
; ; ; ;
Read BuufferLen Read address of Buffer A Read address of Buffer B LR points to next instruction
[LR], #4 will read the value at the address pointed to by the Link Register and then
move the register on by four bytes. Thus at the end of this sequence the value of LR has been updated to point to the next instruction after the parameter block. This parameter passing technique has the advantage of being easy to read. It has, however, the disadvantage of requiring parameters to be when the program is written. Passing the address of the parameter block in via a register allows the papa meters to be changed as the program is running.
xed
R0, #BufferLen R0, [SP, #-4]! R0, =BufferA R0, [SP, #-4]! R0, =BufferA R0, [SP, #-4]! Subr
; ; ; ; ; ;
Buffer Length on the stack Address of Buffer A on the stack Address of Buffer B on the stack
The subroutine must begin by loading parameters into CPU registers as follows:
Subr
; ; ; ;
save working registers to stack Buffer Length in D0 Buffer A starting address Buffer B starting address
; Main function of subroutine R12, {R0, R1, R2, R12, R14} PC, LR ; Recover working registers ; Return to caller
116
CHAPTER 15.
SUBROUTINES
In this approach, all parameters are passed and results are returned on the stack. The stack grows downward (toward lower addresses). This occurs because elements are pushed onto the stack using the pre-decrement address mode. The use of the pre-decrement mode causes the stack pointer to always contain the address of the last occupied location, rather than the next empty one as on some other microprocessors. This implies that you must initialise the stack pointer to a value higher than the largest address in the stack area. When passing parameters on the stack, the programmer must implement this approach as follows: 1. Decrement the system stack pointer to make room for parameters on the system stack, and store them using osets from the stack pointer, or simply push the parameters on the stack. 2. Access the parameters by means of osets from the system stack pointer. 3. Store the results on the stack by means of osets from the systems stack pointer. 4. Clean up the stack before or after returning from the subroutine, so that the parameters are removed and the results are handled appropriately.
15.4
Types Of Parameters
Regardless of our approach to passing parameters, we can specify the parameters in a variety of ways. For example, we can:
pass-by-value
Where the actual values are placed in the parameter list. The name comes from the fact that it is only the value of the parameter that is passed into the subroutine rather than the parameter itself. This is the method used by most high level programming languages.
pass-by-reference
The address of the parameters are placed in the parameter list. The subroutine can access the value directly rather than a copy of the parameter. This is much more dangerous as the subroutine can change a value you don't want it to.
pass-by-name
Rather than passing either the value or a reference to the value a string containing the name of the parameter is passed. This is used by very high level languages or scripting languages. This is very exible but rather time consuming as we need to look up the value associated with the variable name every time we wish to access the variable.
15.5
Program Examples
init1.s
Program 15.1a:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
initiate a simple stack TTL AREA ENTRY Ch10Ex1 Program, CODE, READONLY
Main
;load the top of stack ;push the data onto the stack ;all done
15.5.
PROGRAM EXAMPLES
117
17 18 19 20 21 22 23 24 25 26 27 28 29
Stack1, DATA 0xFFFF 0xDDDD 0xAAAA 0x3333 Data2, DATA 40 0 ;reserve 40 bytes of memory for the stack
Program 15.1b:
init2.s
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
initiate a simple stack TTL AREA ENTRY Ch10Ex2 Program, CODE, READONLY
Main
R7, =Data2 R7, {R1 - R4} &11 Stack1, DATA 0xFFFF 0xDDDD 0xAAAA 0x3333 Data2, DATA 40 0 ;reserve 40 bytes of memory for the stack ;all done
Program 15.1c:
init3.s
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
initiate a simple stack TTL AREA ENTRY Ch10Ex3 Program, CODE, READONLY EQU R1, R2, R3, R4, 0x9000 Value1 Value2 Value3 Value4 ;put some data into registers
118
CHAPTER 15.
SUBROUTINES
17 18 19 20 21 22 23 24 25 26 27 28 29
SWI Value1 Value2 Value3 Value4 AREA DCD DCD DCD DCD AREA ^ DCD END
&11 Data1, DATA 0xFFFF 0xDDDD 0xAAAA 0x3333 Data2, DATA StackStart 0
Stack1
Program 15.1d:
init3a.s
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
initiate a simple stack TTL AREA ENTRY Ch10Ex4 Program, CODE, READONLY EQU R1, R2, R3, R4, 0x9000 Value1 Value2 Value3 Value4 ;put some data into registers
StackStart start LDR LDR LDR LDR LDR STMDB SWI Value1 Value2 Value3 Value4 AREA DCD DCD DCD DCD AREA ^ DCD END
R7, =StackStart R7, {R1 - R4} &11 Data1, DATA 0xFFFF 0xDDDD 0xAAAA 0x3333 Data2, DATA StackStart 0
Stack1
register
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Program 15.1e:
byreg.s
* *
a simple subroutine example program passes a variable to the routine in a register TTL AREA ENTRY Ch10Ex4 Program, CODE, READONLY EQU 0x9000 ;variable stored to register ;branch/link ;store the result of the subroutine ;output to console ;all done
15.5.
PROGRAM EXAMPLES
119
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
* * * * * * * * * * * * * * * * * * Hexdigit
========================= Hexdigit subroutine ========================= Purpose Hexdigit subroutine converts a Hex digit to an ASCII character Initial Condition R0 contains a value in the range 00 ... 0F Final Condition R0 contains ASCII character in the range '0' ... '9' or 'A' ... 'F' Registers changed R0 only Sample case Initial condition Final condition CMP BLE ADD ADD MOV AREA DCB DCB END R0 = 6 R0 = 36 ('6')
R0, #0xA ;is it > 9 Addz ;if not skip the next R0, R0, #"A" - "0" - 0xA ;adjust for A .. F R0, R0, #"0" PC, LR Data1, DATA 6 0 ;convert to ASCII ;return from subroutine ;digit to convert ;storage for ASCII character
Addz
HDigit AChar
Program 15.1f:
bystack.s
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
a more complex subroutine example program passes variables to the routine using the stack TTL AREA ENTRY Ch10Ex5 Program, CODE, READONLY EQU EQU 0x9000 0x0000000F ;declare where top of stack will be ;bit mask for masking out lower nibble ;Top of stack = 9000 ;Load number to register ;load address of string ;and store it ;and store number to stack ;branch/link ;all done
R7, =StackStart R0, Number R1, =String R1, [R7], #-4 R0, [R7], #-4 Binhex &11
* * * * * * * *
========================= Binhex subroutine ========================= Purpose Binhex subroutine converts a 16 bit value to an ASCII string Initial Condition First parameter on the stack is the value
120
CHAPTER 15.
SUBROUTINES
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
* * * * * * * * * * * * * * Binhex
Second parameter is the address of the string Final Condition the HEX string occupies 4 bytes beginning with the address passed as the second parameter Registers changed No registers are affected Sample case Initial condition Final condition top of stack : 4CD0 Address of string The string '4''C''D''0' in ASCII occupies memory ;save stack pointer for later ;push contents of R0 to R6, and LR onto the stack ;init counter ;adjust pointer ;get the number ;get the address of the string ;move past the end of where the string is to be stored ;copy the number ;get the low nibble ;convert to ASCII ;store it ;shift to next nibble ;decr counter ;loop while still elements left ;restore the registers ;return from subroutine
MOV STMDA MOV ADD LDR LDR ADD MOV AND BL STRB MOV SUBS BNE LDMDA MOV
Loop
R0, R2 R0, R0, #Mask Hexdigit R0, [R4], #-1 R2, R2, LSR #4 R1, R1, #1 Loop R8, {R0-R6,R14} PC, LR
* * * * * * * * * * * * * * * * * * Hexdigit
========================= Hexdigit subroutine ========================= Purpose Hexdigit subroutine converts a Hex digit to an ASCII character Initial Condition R0 contains a value in the range 00 ... 0F Final Condition R0 contains ASCII character in the range '0' ... '9' or 'A' ... 'F' Registers changed R0 only Sample case Initial condition Final condition CMP BLE ADD ADD MOV AREA DCD R0 = 6 R0 = 36 ('6')
R0, #0xA ;is the number 0 ... 9? Addz ;if so, branch R0, R0, #"A" - "0" - 0xA ;adjust for A ... F R0, R0, #"0" PC, LR Data1, DATA &4CD0 ;change to ASCII ;return from subroutine ;number to convert
Addz
Number
15.5.
PROGRAM EXAMPLES
121
96 97 98
String
DCB END
4, 0
Program 15.1g:
add64.s
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
a 64 bit addition subroutine TTL AREA ENTRY Ch10Ex6 Program, CODE, READONLY
Main
* * * * * * * * * * * * * * * * * * * * * * * * Add64
========================= Add64 subroutine ========================= Purpose Add two 64 bit values Initial Condition The two parameter values are passed immediately following the subroutine call Final Condition The sum of the two values is returned in R0 and R1 Registers changed R0 and R1 only Sample case Initial condition para 1 = = &0420147AEB529CB8 para 2 = = &3020EB8520473118 Final condition R0 = &34410000 R1 = &0B99CDD0 STMIA MOV SUB LDR LDR LDR LDR ADDS BCC ADD ADD LDMIA MOV AREA DCD DCD R12, {R2, R3, R14} R7, R12 R7, R7, #4 R3, [R7], #-4 R2, [R7], #-4 R1, [R7], #-4 R0, [R7], #-4 R1, R1, R3 Next R0, R0, #1 R0, R0, R2 R12, {R2, R3, R14} PC, LR Data1, DATA &0420147A, &EB529CB8 &3020EB85, &20473118 ;save registers to stack ;copy stack pointer ;adjust to point at LSB of 2nd value ;load successive bytes
Next
;add LS bytes & set carry flag ;branch if carry bit not set ;otherwise add the carry ;add MS bytes ;pop from stack ;and return ;number1 to add ;number2 to add
Value1 Value2
122
CHAPTER 15.
SUBROUTINES
61
END
Program 15.1h:
factorial.s
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
a subroutine to find the factorial of a number TTL AREA ENTRY Ch10Ex6 Program, CODE, READONLY
Main
* * * * * * * * * * * * * * * * * * * * * Factor
========================= Factor subroutine ========================= Purpose Recursively find the factorial of a number Initial Condition R0 contains the number to factorial Final Condition R0 = factorial of number Registers changed R0 and R1 only Sample case Initial condition Number = 5 Final condition FNum = 120 = 0x78 STR STR SUBS BNE MOV SUB B R0, [R12], #4 R14, [R12], #4 R0, R0, #1 F_Cont R0, #1 R12, R12, #4 Return Factor R14, [R12], #-4 R1, [R12], #-4 R0, R1, R0 PC, LR Data1, DATA 5 0 ;push to stack ;push the return address ;subtract 1 from number ;not finished ;Factorial == 1 ;adjust stack pointer ;done ;if not done, call again ;return address ;load to R1 (can't do MUL R0, R0, xxx) ;multiply the result ;and return ;number ;factorial
F_Cont Return
Number FNum
15.6.
PROBLEMS
123
15.6
Problems
Write both a calling program for the sample problem and at least one properly documented subroutine for each problem.
R0
R0
Input: Output:
R0 R0
Test A
43 `C' 0C
Test B
36 `6' 06
R0
R0
. It should convert
R0 R0
STRING
String
42 `B' 32 `2' 46 `F' 30 `0' 0000B2F0
Output:
R0
Input: Output:
R0 Z
Test A
47 `G' FF
Test B
36 `6' 00
Test C
6A `j' FF
isalpha
address of the rst non-alphabetic character in the string in register subroutine you have just dene.
R1
R1
Sample Problems:
Input:
R1 R1
String
Test A String
43 `C' 61 `a' 74 `t'
6100
Output:
String
(CR)
0D CR + 4
(2)
String
+ 0
124
CHAPTER 15.
SUBROUTINES
R0
-ag, if one or more bytes have an odd parity it should clear the
-ag.
Sample Problems:
Input:
R0 Z
String
Test A String
03 47 AF 18 00
Test B String
03 47 AF 19 FF
Output:
Note that 19 16 is 0001 1001 2 which has three 1 bits and is thus has an odd parity.
R0
-ag if the checksums are equal, and reset the ag if they are not.
Sample Problems:
Input:
R0
String
Z
String
03 41 42 43 C6 Set
03
String
61 62 63 C6 Clear
Output:
-ag will be set if the strings are equal, no ags are set if the second is prior to the rst.
-ag will be set if the rst string is lexically less than (prior to)
16
125
126
CHAPTER 16.
Operation
A Register Transfer Language (RTL) / pseudo-code description of what the instruction does. For details of the register transfer language, see section ?? on page ??.
Syntax
<cc> Condition Codes <op1> Data Movement Addressing Modes <op2> Memory Addressing Modes <S> Set Flags bit
Description
Written description of what the instruction does. This will interpret the formal description given in the operation part. It will also describe any additional notations used in the Syntax part.
Exceptions
This gives details of which exceptions can occur during the instruction. Prefetch Abort is not listed because it can occur for any instruction.
Usage
Suggestions and other information relating to how an instruction can be used eectively.
Condition Codes
Indicates what happens to the CPU Condition Code Flags if the set ags option where to be set.
Notes
Contain any additional explanation that we can not t into the previous categories.
Appendix B provides a summary of the more common instructions in a more compact manner, using the operation section only.
ADC
Operation
Syntax Description
ADC
value of
Rn
(Add with Carry) instruction adds the value of and stores the result in
Rd
op1
ADC
R0
R2 R4 R5
and ,
R0 R1
,
and
R2 R3
,
hold
ADDS ADC
R4,R0,R2 R5,R1,R3
ADC
R5,R1,R3
127
128
to:
ADCS
R5,R1,R3
The following instruction produces a single-bit Rotate Left with Extend operation (33-bit rotate through the Carry ag) on
R0
See
ADCS
R0,R0,R0
The N and Z ags are set according to the result of the addition, and the C and V ags are set according to whether the addition generated a carry (unsigned overow) and a signed overow, respectively.
ADD
Operation
Add
Syntax Description
Rd
. The condition code ags are optionally updated, based on the result.
Rn
Usage
The
Rx
use:
Rx, Rx, #1
Constant multiplication of
Rx
by
2n + 1
into
Rd
where the
oset
ADD
The N and Z ags are set according to the result of the addition, and the C and V ags are set according to whether the addition generated a carry (unsigned overow) and a signed overow, respectively.
AND
Operation
Bitwise AND
Syntax Description
The
Rd
Rn
129
Usage
AND
is most useful for extracting a eld from a register, by ANDing the register with a
The N and Z ags are set according to the result of the operation, and the C ag is set to the carry output generated by (see 5.1 on page 45) The V ag is unaected.
op1
B, BL
Operation
Syntax Description
cc L : LR PC + 8 cc : PC PC + oset B L cc oset
The
(Branch) and
BL
R14
The
BL
).
(Branch and Link) instruction stores a return address in the link register (
LR
or
The
is calculated by adding the oset to the program counter ( of the branch instruction plus 8.
oset
species the target address of the branch. The address of the next instruction
PC
32MB.
The
BL
LR
to the
PC
Executing a
MOV PC,R14
instruction.
Storing a group of registers and R14 to the stack on subroutine entry, using an instruction of the form:
and then restoring the register values and returning with an instruction of the form:
Branching backwards past location zero and forwards over the end of the 32-bit address space is UNPREDICTABLE.
CMP
Operation
Compare
Syntax Description
CMP
(Compare) instruction compares a register value with another arithmetic value. from
The condition ags are updated, based on the result of subtracting subsequent instructions can be conditionally executed.
Condition Codes
op1
Rn
, so that
The N and Z ags are set according to the result of the subtraction, and the C and V ags are set according to whether the subtraction generated a borrow (unsinged underow) and a signed overow, respectively.
130
EOR
Operation
Exclusive OR
Syntax Description
Rn
op1
Rd
Usage
EOR can be used to invert selected bits in a register. For each bit, EOR with 1 inverts that bit, and EOR with 0 leaves it unchanged.
Condition Codes
The N and Z ags are set according to the result of the operation, and the C ag is set to the carry output bit generated by the shifter. The V ag is unaected.
LDM
Operation
Load Multiple
Syntax Description
IA: addr Rn IB: addr Rn + 4 DA: addr Rn - (# registers * 4) + 4 DB: addr Rn - (# registers * 4) for each register Ri in registers IB: addr addr + 4 DB: addr addr - 4 Ri M(addr) IA: addr addr + 4 DA: addr addr - 1 ! : Rn addr LDM cc mode Rn ! registers
, { } The LDM (Load Multiple) instruction is useful for block loads, stack operations and procedure exit sequences. It loads a subset, or possibly all, of the general-purpose registers from sequential memory locations. The general-purpose registers loaded can include the the
if
cc
PC
PC
registers mode
Rn
points to the memory local to load the values from. Each of the registers is loaded in turn, reading each value from the next memory address as , one of: IB DB IA DA Increment Before Decrement Before Increment After Decrement After ) causes the base register to be modied to hold the
The base register writeback option ( address of the nal valued loaded.
The register are loaded in sequence, the lowest-numbered register from the lowest memory address, through to the highest-numbered register from the highest memory address. If the
PC R15
(
) is specied in the register list, the instruction causes a branch to the address
PC
Data Abort
Condition Codes
131
Notes
Rn
Rn
is specied in
is UNPREDICTABLE.
registers
LDR
Operation Syntax Description
Load Register
The
(Load Register) instruction loads a word from the memory address calculated by
If the
PC
is specied as register
Rd Rd
.
independent code. Combined with a suitable addressing mode, the destination register is the branches to that address.
PC
LDR
data to be loaded into a general-purpose register where its value can be manipulated. If
PC
LDR
instruction with
If
Rn
op2 op2
LDRB
species base register writeback (!), and the same register is specied for
Rd
and
If the
UNPREDICTABLE.
PC R15
(
) is specied for
Rd
LDRB
Operation
Syntax Description
The by
(Load Register Byte) instruction loads a byte from the memory address calculated
, zero-extends the byte to a 32-bit word, and writes the word to register
Rd
Exceptions Usage
Data Abort
LDRB
allows 8-bit memory data to be loaded into a general-purpose register where it can
independent code.
Condition Codes
PC
If the If
Rn MOV
Operation
op2
PC R15
(
) is specied for
Rd
species base register writeback (!), and the same register is specied for
Rd
and
Move
132
Syntax Description
MOV
The
cc S Rd op1
,
MOV
op1
Rd
. The
MOV
is used to: Move a value from one register to another. Put a constant value into a register. Perform a shift without any other arithmetic or logical operation. A left shift by n can be used to multiply by 2 . When the
PC
MOV
page 129).
Condition Codes
PC, LR
, and
BL
on
The N and Z ags are set according to the value moved (post-shift if a shift is specied), and the C ag is set to the carry output bit generated by the shifter (see 5.1 on page 45). The V ag is unaected.
MVN
Operation
Move Negative
Syntax Description
(Move Negative) instruction moves the logical one's complement of the value of . The condition code ags are optionally updated,
MVN
Write a negative value into a register. Form a bit mask. Take the one's complement of a value.
Condition Codes
The N and Z ags are set according to the result of the operation, and the C ag is set to the carry output bit generated by the shifter (see 5.1 on page 45). The V ag is unaected.
ORR
Operation
Bitwise OR
Syntax Description
(Logical OR) instruction performs a bitwise (inclusive) OR of the value of register , and stores the result in the destination register
Rd
The
Usage
ORR
can be used to set selected bits in a register. For each bit, OR with 1 sets the bit, and
The N and Z ags are set according to the result of the operation, and the C ag is set to the carry output bit generated by the shifter (see 5.1 on page 45). The V ag is unaected.
133
SBC
Operation
Syntax Description
(Subtract with Carry) instruction is used to synthesize multi-word subtraction. and the value of NOT(Carry ag) from the value of , and stores the result in the destination register
Rn
Rd
Usage
If register pairs
R0 R1
,
and
R2 R3
,
R0
and
R2 R4 R5
,
SUBS SBC
Condition Codes
R4,R0,R2 R5,R1,R3
The N and Z ags are set according to the result of the subtraction, and the C and V ags are set according to whether the subtraction generated a borrow (unsigned underow) and a signed overow, respectively.
Notes
If
0 if no borrow occurs 1 if a borrow does occur In other words, the C ag is used as a NOT(borrow) ag. This inversion of the borrow condition is usually compensated for by subsequent instructions. For example:
The
SBC
and
RSC
a normal subtraction if C == 1 and subtracting one more than usual if C == 0. The HS (unsigned higher or same) and LO (unsigned lower) conditions are equivalent to CS (carry set) and CC (carry clear) respectively.
STM
Operation
Store Multiple
Syntax Description
IA: addr Rn IB: addr Rn + 4 DA: addr Rn - (# registers * 4) + 4 DB: addr Rn - (# registers * 4) for each register Ri in registers IB: addr addr + 4 DB: addr addr - 4 M(addr) Ri IA: addr addr + 4 DA: addr addr - 4 ! : Rn addr STM cc mode Rn ! registers
, { } The
if
cc
STM (Store Multiple) instruction stores a subset (or possibly all) of the general-purpose
Rregisters
mode
is stored in turn, storing each register in the next memory address as directed
Rn
species the base register used to store the registers. Each register given
134
be stored. The registers are stored in sequence, the lowest-numbered register to the lowest memory address, through to the highest-numbered register to the highest memory address. If
Exceptions Usage
registers
(
Rn
) is modied
R15 PC
) is specied in
registers
Data Abort
STM
STM
LDM
return address and general-purpose register values on to the stack, updating the stack
If If
R15 PC Rn Rn
( If
is specied as
registers
Rn
! registers
Rn
The value of
Rn
Rn
is UNPREDICTABLE.
STR
Operation Syntax Description
Store Register
STR
The
calculated by
Exceptions Usage
Rd
Data Abort Combined with a suitable addressing mode, register into memory. Using the which facilitates position-independent code.
PC
STR
Condition Codes
Using the If
Rn
op2
PC
Rd
species base register writeback (!), and the same register is specied for
Rd
and
op2
STRB
Operation Syntax Description
STRB
register
Exceptions
Rd
(Store Register Byte) instruction stores a byte from the least signicant byte of to the memory address calculated by .
op2
Data Abort
135
Usage
STRB
PC
writes the least signicant byte of a as the base register allows PC-relative
Specing the
Rn SUB
Operation
If
op2
PC
Rd
) is UNPREDICTABLE.
species base register writeback (!), and the same register is specied for
Rd
and
Subtract
Syntax Description
Rd
Rn
Usage
SUB
is used to subtract one value from another to produce a third. To decrement a register
value (in
Rx
) use:
SUBS SUBS
Rx, Rx, #1
is useful as a loop counter decrement, as the loop branch can test the ags for the
CMP
Condition Codes
Rx, #0
Rx
The N and Z ags are set according to the result of the subtraction, and the C and V ags are set according to whether the subtraction generated a borrow (unsigned underow) and a signed overow, respectively.
Notes
If
1 if no borrow occurs 0 if a borrow does occur In other words, the C ag is used as a NOT(borrow) ag. This inversion of the borrow condition is usually compensated for by subsequent instructions. For example:
The
SBC
and
RSC
a normal subtraction if C == 1 and subtracting one more than usual if C == 0. The HS (unsigned higher or same) and LO (unsigned lower) conditions are equivalent to CS (carry set) and CC (carry clear) respectively.
SWI
Operation
Software Interrupt
cc : R14_svc PC + 8 cc : SPSR_svc CPSR cc : CPSR(mode) Supervisor cc : CPSR(I) 1 (Disable Interrupts) cc : PC 0x00000008 SWI cc value
Causes a SWI exception (see 3.4 on page 29). Software interrupt
136
Usage
The
SWI
instruction is used as an operating system service call. The method used to select
which operating system service is required is specied by the operating system, and the Two typical methods are:
SWI
exception handler for the operating system determines and provides the requested service.
and any parameters needed by the selected service are passed in other general-purpose registers.
Condition Codes
value value
species which service is required, and any parameters needed by the selected
R0
The ags will be eected by the operation of the software interrupt. It is not possible to say how they will be eected. The status of the condition code ags is unknown after a software interrupt is UNKNOWN.
SWP
Operation
Swap
Syntax Description
Rn Rn Rd
SWP
Rm
Rm
Rd
. If
Exceptions Usage
instructions
If the
Semaphore
Condition Codes
PC
Rn
Rd
), address (
Rn
) or the value (
Rm
), the result is
Rn
and
Rm
, or
Rn
and
Rd
If a data abort is signaled on either the load access or the store access, the loaded value is not written to not occur. . If a data abort is signaled on the load access, the store access does
Rd
SWPB
Operation
Swap Byte
Syntax Description
Rn
SWPB
32-bit word, and the word is written to register the byte value at the memory address.
Rn
Rm
, this instruction swaps the value of the least signicant byte of the register and
Rd
Rm Rd
is
137
Exceptions Usage
SWPB
shown for
Condition Codes
SWP
instructions in
Semaphore instructions
, or
If the
PC
is specied for
Rd Rn
,
Rm Rn
Rm
, or
Rn
and
Rd
If a data abort is signaled on either the load access or the store access, the loaded value is not written to not occur. . If a data abort is signaled on the load access, the store access does
Rd
138
B
CS CC EQ NE VS VC
Generic
Carry Clear Equal (Zero Set) Not Equal (Zero Clear) Overow Set Overow Clear
HI HS LO LS
Higer Than
Unsigned
GT GE LT LE MI PL
Greater Than Greater Than or Equal Less Than Less Than or Equal Minus (Negative) Plus (Positive)
Signed
Rm Rm , Rm , Rm , Rm , Rm , Rm , Rm , Rm , Rm ,
value
LSL LSL LSR LSR ASR ASR ROR ROR RRX
op1 op1 op1 op1 op1 op1 op1 op1 op1 op1 op1
IR(value)
Rm Rm Rm Rm Rm Rm + Rm + Rm > Rm >
IR(value)
CPSR(C)
Rs Rs Rs value Rs
>
IR(value) IR(value)
(4:0)
Rm >
CPSR(C)
[ n , # [ n, m] [ , m,
value ]!
Rn Rn Rn Rn op2 Rn op2 Rn
+ IR(value) + + (
Rm Rm shift Rm Rm shift
IR(value))
+ IR(value) +
op2
value
Rn Rn Rn Rn Rm Rn Rn Rm shift
+ +
op2
+ (
IR(value))
+ IR(value)
IR(value)
Where
shift
is one of:
RRX
op1
139
140
ARM Instructions
Add with Carry Add Bitwise AND Branch Branch and Link Compare Exclusive OR Load Register Load Register Byte Move Move Negative Bitwise OR Subtract with Carry Store Register Store Register Byte Subtract Software Interrupt Swap Swap Byte
cc S cc S cc S cc cc CMP cc EOR cc S LDR cc LDR cc B MOV cc S MVN cc S ORR cc S SBC cc S STR cc STR cc S SUB cc S SWI cc SWP cc SWP cc B
Rd Rn Rd Rn Rd Rn
, , , ,
, , ,
oset oset Rn op1 Rd Rn op1 Rd op2 Rd op2 Rd op1 Rd op1 Rd Rn op1 Rd Rn op1 Rd op2 Rd op2 Rd Rn op1 value
, , , , , , , , , , , , , ,
Rd Rm Rn Rd Rm Rn
, , [ , [ ,
] ]
cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc
: : :
: PC : LR : PC : CSPR : : : : : : : :
Rd Rd Rd
: M( : M( : : :
Rd Rd Rd Rd Rd Rd Rd Rd
(7:0) (31:8)
: M( : M(
Rd Rd Rn Rd Rn
op2 op2
)
) )
op1 op1 op1 oset oset Rn op1 Rn op1 op2 op2 op1 op1 Rn op1 Rn op1
Rn Rn Rn
( + + & PC + PC + 8 PC + ) M( 0 ) M( ) |
+ CPSR(C)
Rd Rd Rn
- CPSR(C)
(7:0) -
op1
(7:0) )(7:0)
Rn Rm Rn Rm
M( M(
) )(7:0)
(7:0)
Index
Characters ASCII . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 International . . . . . . . . . . . . . . . . . . . . . . . . . . . 82 Unicode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82 Condition Codes . . . . . . . . . . . 2829, 3132, 4243 Carry Flag . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 Mnemonics . . . . . . . . . . . . . . . . . . . . . . . . . 31, 42 Negative Flag . . . . . . . . . . . . . . . . . . . . . . . . . . 29 Overow Flag . . . . . . . . . . . . . . . . . . . . . . . . . . 29 Zero Flag . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2930 Data Abort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 Fast Interrupt . . . . . . . . . . . . . . . . . . . . . . . . . . 30 Interrupt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 Prefetch Abort . . . . . . . . . . . . . . . . . . . . . . . . . 30 Reset . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 Software Interrupt . . . . . . . . . . . . . . . . . . . . . . 29 Undened . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 Instructions ADC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127 ADD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128 AND . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128 B, BL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129 CMP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129 EOR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130 LDM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130 LDR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131 LDRB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131 MOV . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131 MVN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132 ORR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132 SBC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133 STM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133 STR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134 STRB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134 SUB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135 SWI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135 SWP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136 SWPB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136 Programs add.s . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 add2.s . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5960 add64.s . . . . . 6364, 6970, 99100, 121122 addbcd.s . . . . . . . . . . . . . . . . . . . . . . . . . . 100101 bigger.s . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62, 69 byreg.s . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118119 Registers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2528 General Purpose ( Link Register ( Stack Pointer ( bystack.s . . . . . . . . . . . . . . . . . . . . . . . . . . 119121 countneg.s . . . . . . . . . . . . . . . . . . . . . . . . . . 7374 countneg16.s . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 cstrcmp.s . . . . . . . . . . . . . . . . . . . . . . . . . . . 8687 dectonib.s . . . . . . . . . . . . . . . . . . . . . . . . . . . 9394 divide.s . . . . . . . . . . . . . . . . . . . . . . . . . . . 102103 factorial.s . . . . . . . . . . . . . . . . . . . 6465, 70, 122 halftobin.s . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95 head.s . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107108 init1.s . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116117 init2.s . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117 init3.s . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117118 init3a.s . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 insert.s . . . . . . . . . . . . . . . . . . . . . . . . . . . 105106 insert2.s . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106 invert.s . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 largest16.s . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75 move16.s . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 mul16.s . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 mul32.s . . . . . . . . . . . . . . . . . . . . . . . . . . . 101102 nibble.s . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 nibtohex.s . . . . . . . . . . . . . . . . . . . . . . . . . . . 9192 nibtoseg.s . . . . . . . . . . . . . . . . . . . . . . . . . . . 9293 normalize.s . . . . . . . . . . . . . . . . . . . . . . . . . . 7576 padzeros.s . . . . . . . . . . . . . . . . . . . . . . . . . . . 8485 search.s . . . . . . . . . . . . . . . . . . . . . . . . . . . 106107 setparity.s . . . . . . . . . . . . . . . . . . . . . . . . . . . 8586 shiftleft.s . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6061 skipblanks.s . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84 sort.s . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108 strcmp.s . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8788 strlen.s . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8384 strlencr.s . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8283 sum16.s . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72 sum16b.s . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7273 ubcdtohalf.s . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94 ubcdtohalf2.s . . . . . . . . . . . . . . . . . . . . . . . . 9495 wordtohex.s . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
) . . . . . . . . . . . . . 25 ) . . . . . . . . . . . . 27 ) . . . . . . . . . . 28
) . . . . . . . . . . . . . . . . 27 ) . . . . . . . . . . . . . . . . 26
141
142
INDEX
Terminated . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81