




























































































Study with the several resources on Docsity
Earn points by helping other students or get them with a premium plan
Prepare for your exams
Study with the several resources on Docsity
Earn points to download
Earn points by helping other students or get them with a premium plan
Community
Ask the community for help and clear up your study doubts
Discover the best universities in your country according to Docsity users
Free resources
Download our free guides on studying techniques, anxiety management strategies, and thesis advice from Docsity tutors
engineering
Typology: Study notes
1 / 156
This page cannot be seen from the preview
Don't miss anything!
ARM: Assembly Language Programming
August 31, 2004
vi CONTENTS
viii LIST OF PROGRAMS
12.3 addbcd.s Add two packed BCD numbers to give a packed BCD result..... 100 12.4a mul16.s 16 bit binary multiplication........................ 101 12.4b mul32.s Multiply two 32 bit number to give a 64 bit result (corrupts R0 and R1) 12.5 divide.s Divide a 32 bit binary no by a 16 bit binary no store the quotient and remainder there is no 'DIV' instruction in ARM!............ 102
13.1a insert.s Examine a table for a match - store a new entry at the end if no match found.................................... 105 13.1b insert2.s Examine a table for a match - store a new entry if no match found extends insert.s............................... 106 13.2 search.s Examine an ordered table for a match.................. 106 13.3 head.s Remove the rst element of a queue................... 107 13.4 sort.s Sort a list of values simple bubble sort................. 108
15.1a init1.s Initiate a simple stack........................... 116 15.1b init2.s Initiate a simple stack........................... 117 15.1c init3.s Initiate a simple stack........................... 117 15.1d init3a.s Initiate a simple stack........................... 118 15.1e byreg.s A simple subroutine example program passes a variable to the routine in a register................................. 118 15.1f bystack.s A more complex subroutine example program passes variables to the routine using the stack.......................... 119 15.1g add64.s A 64 bit addition subroutine....................... 121 15.1h factorial.s A subroutine to nd the factorial of a number............. 122
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 era was charac- 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 ap- pear 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 departments could now buy their own minis. 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. For the rst time, each student was able to access a real computer. Unfortunately, microprocessors appeared before the introduction of low-cost memory (both primary and secondary). Students had to program microprocessors in assembly language because the only storage mechanism was often a ROM with just enough 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 post-microprocessor era. Today's personal computers have more power and storage capacity than many of yesterday's mainframes, and they have a range of powerful software tools that were undreamed of in the 1970s. Moreover, the computer science curriculum of the 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 ma- terial 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 of the computer, you 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 xi
The stack and subroutines How procedures are called, and parameters passed and returned from procedures. By using an assembly language you can readily teach the passing of parameters by value and by reference. The use of local variables and re-entrant programming can also be taught. This 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 assem- bly 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.
Run-time support for high-level languages A high-performance processor like the ARM provides facilities that support run-time check- ing in high-level languages. For example, the programming techniques document lists a series of programs that interface with 'C' and provide run-time checking for errors such as an attempt to divide a number by zero.
Protected-mode operation Members of the ARM family operate in either a priviledge mode 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 secure or protected environments in which the eects of an error in one application can be prevented from harming the operating system (or other applications).
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.
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
This is a machine language, or object, program. If this program were entered into the memory of an ARM-based microcomputer, the microcomputer would be able to execute it directly.
1.3 The Binary Programming Problem
There are many diculties associated with creating programs as object, or binary machine lan- guage, programs. These are some of the problems:
For example, the following version of the addition object program contains a single bit error. Try to nd it:
Although the computer handles binary numbers with ease, people do not. People nd binary programs long, tiresome, confusing, and meaningless. Eventually, a programmer may start re- membering some of the binary codes, but such eort should be spent more productively.
1.4 Using Octal or Hexadecimal
We can improve the situation somewhat by writing instructions using octal or hexadecimal num- bers, 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:
E59f E E58F
At the very least, the hexadecimal version is shorter to write and not quite so tiring to examine.
Errors are somewhat easier to nd in a sequence of hexadecimal digits. The erroneous version of the addition program, in hexadecimal form, becomes:
Hexadecimal Binary Decimal Digit Equivalent Equivalent 0 0000 0 1 0001 1 2 0010 2 3 0011 3 4 0100 4 5 0101 5 6 0110 6 7 0111 7 8 1000 8 9 1001 9 A 1010 10 B 1011 11 C 1100 12 D 1101 13 E 1110 14 F 1111 15
Table 1.1: Hexadecimal Conversion Table
E59f E E68F
The mistake is far more obvious.
The hexadecimal version of the program is still dicult to read or understand; for example, it does not distinguish operations from data or addresses, nor does the program listing provide any suggestion as to what the program does. What does 3038 or 31C0 mean? Memorising a card full of codes is hardly an appetising proposition. Furthermore, the codes will be entirely dierent for a dierent microprocessor and the program will require a large amount of documentation.
1.5 Instruction Code Mnemonics
An obvious programming improvement is to assign a name to each instruction code. The instruc- tion code name is called a mnemonic or memory jogger.
In fact, all microprocessor manufacturers provide a set of mnemonics for the microprocessor in- struction 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 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. Some instructions do (for example, ADD, AND, ORR), others have obvious contractions (such as SUB for subtraction, EOR for exclusive-OR), while still others have neither. The result is such mnemonics as BIC, STMIA, and even MRS. Most manufacturers come up with some reasonable names and some hopeless ones. However, users who devise their own mnemonics rarely do much better.
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 A for Accumu- lator) while others may have only historical signicance. Again, we will use the manufacturer's suggestions simply to promote standardisation.
If we use standard ARM instruction and register mnemonics, as dened by Advanced RISC Ma- chines, our ARM addition program becomes:
All of these features, of course, involve additional cost and memory. Microcomputers generally have much simpler assemblers than do larger computers, but the tendency is always for the size of assemblers to increase. You will often have a choice of assemblers. The important criterion is not how many o-beat features the assembler has, but rather how convenient it is to use in normal practice.
1.7 Disadvantages of Assembly Language
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 R0,% ADD R0,% LD %6004,R
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.
1.8 High-Level Languages
The solution to many of the diculties associated with assembly language programs is to use, insted, high-level or procedure-oriented 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. If, for exampe, you can express what you want the computer to do in algebraic notation, you can write your FORTRAN (For mula Translation Language), the oldest of the high-level languages. Now, if you want to add two numbers, you just tell the computer:
sum = num1 + num2;
That is a lot simpler (and shorter) than either the equivalent machine language program or the equivalent assembly language program. Other high-level languages include COBOL (for business applications), BASIC (a cut down version of FORTRAN designed to prototype ideas before codeing them in full), C (a systems-programming language), C++ and JAVA (object-orientated general development languages).
Clearly, high-level languages make program easier and faster to write. A common estimate is that a programmer can write a program about ten times as fast in a high-level langauge as in assembly language. That is just writing the program; it does not include problem denition, program design, debugging testing or documentation, all of which become simpler and faster. The high-level language program is, for instance, partly self-documenting. Even if you do not know 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.