Preface

Few industries are as quick to change as those based on technology, and computer technology is no exception. Since the First Edition of ARM Assembly Language: Fundamentals and Techniques was published in 2009, ARM Limited and its many partners have introduced a new family of embedded processors known as the Cortex-M family. ARM is well known for applications processors, such as the ARM11, Cortex-A9, and the recently announced Cortex-5x families, which provide the processing power to modern cell phones, tablets, and home entertainment devices. ARM is also known for real-time processors, such as the Cortex-R4, Cortex-R5, and Cortex-R7, used extensively in deeply embedded applications, such as gaming consoles, routers and modems, and automotive control systems. These applications are often characterized by the presence of a real-time operating system (RTOS). However, the Cortex-M family focuses on a well-established market space historically occupied by 8-bit and 16-bit processors. These applications differ from real-time in that they rarely require an operating system, instead performing one or only a few functions over their lifetime. Such applications include game controllers, music players, automotive safety systems, smart lighting, connected metering, and consumer white goods, to name only a few. These processors are frequently referred to as microcontrollers, and a very successful processor in this space was the ubiquitous 8051, introduced by Intel but followed for decades by offerings from numerous vendors. The 68HC11, 68HC12, and 68HC16 families of microcontrollers from Motorola were used extensively in the 1980s and 1990s, with a plethora of offerings including a wide range of peripherals, memory, and packaging options. The ease of programming, availability, and low cost is partly responsible for the addition of smart functionality to such common goods as refrigerators and washers/dryers, the introduction of airbags to automobiles, and ultimately to the cell phone.

In early applications, a microcontroller operating at 1 MHz would have provided more than sufficient processing power for many applications. As product designers added more features, the computational requirements increased and the need for greater processing power was answered by higher clock rates and more powerful processors. By the early 2000s, the ARM7 was a key part of this evolution. The early Nokia cell phones and Apple iPods were all examples of systems that performed several tasks and required greater processing power than was available in microcontrollers of that era. In the case of the cell phone, the processor was controlling the user interface (keyboard and screen), the cellular radio, and monitoring the battery levels. Oh, and the Snake game was run on the ARM7 as well! In the case of the iPod, the ARM7 controlled the user interface and battery monitoring, as with the cell phone, and handled the decoding of the MP3 music for playing through headphones. With these two devices our world changed forever—ultimately phones would play music and music players would make phone calls, and each would have better games and applications than Snake!

In keeping with this trend, the mix of ARM’s processor shipments is changing rapidly. In 2009 the ARM7 accounted for 55% of the processor shipments, with all Cortex processors contributing only 1%.* By 2012 the ARM7 shipments had dropped to 36%, with the Cortex-M family shipments contributing 22%. This trend is expected to continue throughout the decade, as more of the applications that historically required only the processing power of an 8-bit or 16-bit system move to the greater capability and interoperability of 32-bit systems. This evolution is empowering more features in today’s products over those of yesterday. Consider the capabilities of today’s smart phone to those of the early cell phones! This increase is made possible by the significantly greater computing power available in roughly the same size and power consumption of the earlier devices. Much of the increase comes through the use of multiple processors. While early devices were capable of including one processor in the system, today’s systems include between 2 and 8 processors, often different classes of processors from different processor families, each performing tasks specific to that processor’s capabilities or as needed by the system at that time. In today’s System-on-Chip (SoC) environment, it is common to include both application processors and microcontrollers in the same device. As an example, the Texas Instruments OMAP5 contains a dual-core Cortex-A15 application processor and two Cortex-M4 microcontrollers. Development on such a system involves a single software development system for both the Cortex-A15 and the Cortex-M4 processors. Having multiple chips from different processor families and vendors adds to the complexity, while developing with processors all speaking the same language and from the same source greatly simplifies the development.

All this brings us back to the issue raised in the first edition of this book. Why should engineers and programmers spend time learning to program in assembly language? The reasons presented in the first edition are as valid today as in 2009, perhaps even more so. The complexity of the modern SoCs presents challenges in communications between the multiple processors and peripheral devices, challenges in optimization of the sub-systems for performance and power consumption, and challenges in reducing costs by efficient use of memory. Knowledge of the assembly language of the processors, and the insight into the operation of the processors that such knowledge provides, is often the key to the timely and successful completion of these tasks and launch of the product. Further, in the drive for performance, both in speed of the product to the user and in a long battery life, augmenting the high-level language development with targeted use of hand-crafted assembly language will prove highly valuable—but we don’t stop here. Processor design remains a highly skilled art in which a thorough knowledge of assembly language is essential. The same is true for those tasked with compiler design, creating device drivers for the peripheral subsystems, and those producing optimized library routines. High quality compilers, drivers, and libraries contribute directly to performance and development time. Here a skilled programmer or system designer with a knowledge of assembly language is a valuable asset.

In the second edition, we focus on the Cortex-M4 microcontroller in addition to the ARM7TDMI. While the ARM7TDMI still outsells the Cortex-M family, we believe the Cortex-M family will soon overtake it, and in new designs this is certainly true. The Cortex-M4 family is the first ARM microcontroller to incorporate optional hardware floating-point. Chapter 9 introduces floating-point computation and contrasts it with integer computation. We present the floating-point standard of 1985, IEEE 754-1985, and the recent revision to the standard, the IEEE 754-2008, and discuss some of the issues in the use of floating-point which are not present in integer computation. In many of the chapters, floating-point instructions will be included where their usage would present a difference from that of integer usage. As an example, the floating-point instructions use a separate register file from the integer register file, and the instructions which move data between memory and these registers will be discussed in Chapters 3, 9, and 12. Example programs are repeated with floating-point instructions to show differences in usage, and new programs are added which focus on specific aspects of floating-point computation. While we will discuss floating-point at some length, we will not exhaust the subject, and where useful we will point the reader to other references.

The focus of the book remains on second- or third-year undergraduate students in the field of computer science, computer engineering, or electrical engineering. As with the first edition, some background in digital logic and arithmetic, high-level programming, and basic computer operation is valuable, but not necessary. We retain the aim of providing not only a textbook for those interested in assembly language, but a reference for coding in ARM assembly language, which ultimately helps in using any assembly language.

In this edition we also include an introduction to Code Composer Studio (from Texas Instruments) alongside the Keil RealView Microcontroller Development Kit. Appendices A and B cover the steps involved in violating just about every programming rule, so that simple assembly programs can be run in an otherwise advanced simulation environment. Some of the examples will be simulated using one of the two tools, but many can be executed on an actual hardware platform, such as a Tiva™ Launchpad from TI. Code specifically for the Tiva Launchpad will be covered in Chapter 16. In the first edition, we included a copy of the ARM v4T Instruction Set as Appendix A. To do so and include the ARM Thumb-2 and ARM FPv4-SP instruction sets of the Cortex-M4 would simply make the book too large. Appropriate references are highlighted in Section 1.7.4, all of which can be found on ARM’s and TI’s websites.

The first part of the book introduces students to some of the most basic ideas about computing. Chapter 1 is a very brief overview of computing systems in general, with a brief history of ARM included in the discussion of RISC architecture. This chapter also includes an overview of number systems, which should be stressed heavily before moving on to any further sections. Floating-point notation is mentioned here, but there are three later chapters dedicated to floating-point details. Chapter 2 gives a shortened description of the programmer’s model for the ARM7TDMI and the Cortex-M4—a bit like introducing a new driver to the clutch, gas pedal, and steering wheel, so it’s difficult to do much more than simply present it and move on. Some simple programs are presented in Chapter 3, mostly to get code running with the tools, introduce a few directives, and show what ARM and Thumb-2 instructions look like. Chapter 4 presents most of the directives that students will immediately need if they use either the Keil tools or Code Composer Studio. It is not intended to be memorized.

The next chapters cover topics that need to be learned thoroughly to write any meaningful assembly programs. The bulk of the load and store instructions are examined in Chapter 5, with the exception of load and store multiple instructions, which are held until Chapter 13. Chapter 6 discusses the creation of constants in code, and how to create and deal with literal pools. One of the bigger chapters is Chapter 7, Logic and Arithmetic, which covers all the arithmetic operations, including an optional section on fractional notation. As this is almost never taught to undergraduates, it’s worth introducing the concepts now, particularly if you plan to cover floating-point. If the course is tight for time, you may choose to skip this section; however, the subject is mentioned in other chapters, particularly Chapter 12 when a sine table is created and throughout the floating-point chapters. Chapter 8 highlights the whole issue of branching and looks at conditional execution in detail. Now that the Cortex-M4 has been added to the mix, the IF-THEN constructs found in the Thumb-2 instruction set are also described.

Having covered the basics, Chapters 9 through 11 are dedicated to floating-point, particularly the formats, registers used, exception types, and instructions needed for working with single-precision and half-precision numbers found on the Cortex-M4 with floating-point hardware. Chapter 10 goes into great detail about rounding modes and exception types. Chapter 11 looks at the actual uses of floating-point in code—the data processing instructions—pointing out subtle differences between such operations as chained and fused multiply accumulate. The remaining chapters examine real uses for assembly and the situations that programmers will ultimately come across. Chapter 12 is a short look at tables and lists, both integer and floating-point. Chapter 13, which covers subroutines and stacks, introduces students to the load and store multiple instructions, along with methods for passing parameters to functions. Exceptions and service routines for the ARM7TDMI are introduced in Chapter 14, while those for v7-M processors are introduced in Chapter 15. Since the book leans toward the use of microcontroller simulation models, Chapter 16 introduces peripherals and how they’re programmed, with one example specifically targeted at real hardware. Chapter 17 discusses the three different instruction sets that now exist—ARM, Thumb, and Thumb-2. The last topic, mixing C and assembly, is covered in Chapter 18 and may be added if students are interested in experimenting with this technique.

Ideally, this book would serve as both text and reference material, so Appendix A explains the use of Code Composer Studio tools in the creation of simple assembly programs. Appendix B has an introduction to the use of the RealView Microcontroller Development Kit from Keil, which can be found online at http://www.keil.com/demo. This is certainly worth covering before you begin coding. The ASCII character set is listed in Appendix C, and a complete program listing for an example found in Chapter 15 is given as Appendix D.

A one-semester (16-week) course should be able to cover all of Chapters 1 through 8. Depending on how detailed you wish to get, Chapters 12 through 16 should be enough to round out an undergraduate course. Thumb and Thumb-2 can be left off or covered as time permits. A two-semester sequence could cover the entire book, including the harder floating-point chapters (9 through 11), with more time allowed for writing code from the exercises.


ARM 2012 Annual Report, see www.­arm.­com