Chapter 4. Assembly Language Programming

In this chapter, we will cover the following:

  • Writing Cortex-M4 assembly language
  • Passing parameters between C and the assembly language
  • Handling interrupts in assembly language
  • Implementing a jump table
  • Debugging assembly language

Introduction

This chapter explains how to write functions in assembly language. Assembly language is a low-level programming language that is specific to a particular computer architecture. So, unlike programs written in high-level languages, programs written in assembly language cannot be easily ported to other hardware architectures. Assembly language programs are converted into object code by a program called an assembler. In practice, assembly language is used only rarely and most embedded software is written in a high-level language, such as C. Assembly language is only used when the programmer needs precise control over the machine architecture and needs to access specific registers or when execution time is an important consideration. Such occasions typically occur during the following:

  • Initializing the system
  • Servicing I/O devices
  • Handling interrupts

Assembly language programmers need a model of the computer architecture to enable them to write programs. This so called programmers' model identifies the registers, memory model, and instruction set for a particular machine architecture. The Cortex-M4 programmers' model is described in the ARMv7-M Architecture Reference Manual (please note that ARM restricts access to this document, but copies are available via third parties). Chapter A2 identifies 13 general-purpose 32-bit registers (R0-R12) and three additional special registers (R13-R15) comprising Stack Pointer (SP), Link Register (LR), and Program Counter (PC). Chapter A3 describes a flat address space that is 232 bytes (4 GB) in size, and it identifies specific regions that are reserved for code, data, and memory-mapped I/O devices. The large number of instructions that are supported by the ARMv7-M architecture makes the prospect of writing an assembly language program quite daunting. A good strategy is to index instructions according to functionality (for example, branch, data processing, and data movement (load/store, and so on) as presented in Chapter A4 of the reference manual.

The architecture supports a combination of 16-bit (Thumb) and 32-bit (ARM) instruction formats in an instruction set that is known as Thumb-2 technology. ARM's Unified Assembler Language (UAL) was developed to support both 16-bit and 32-bit instructions. We can specify a 32-bit instruction format using the .W (wide) suffix or the 16-bit format using the .N (narrow) suffix. If we omit the suffix, then the assembler chooses for us based on other constraints. For example, if the instruction references a high register (R8-R13), then a 32-bit variant must be used as most 16-bit instructions can only reference R0-R7. Instructions may also include other optional suffixes that identify the following:

  • Status register flags in the Program Status Register (PSR) {cond} that determine execution (such as for branch instructions)
  • If the condition flags are updated {S}
  • The element size specified either as unsigned byte {B}, signed byte {SB}, unsigned half-word {H}, signed half-word {SH} or word (default)

The startup_stm32f407xx.s file that we include in all our projects is written in assembly language (conventionally, ARM file extensions, .s and .a, identify assembly language source code files). This is because one of its tasks is to set the Stack Pointer (SP) and writing to a specific register is impossible in C. Assembly language uses a mnemonic to represent each machine instruction. Other instructions called pseudo-instructions or assembler directives give commands to the assembler itself. Each line of the program combines instruction and pseudo-instruction mnemonics with operands and labels to carry out each program step. Labels may be included to act as symbolic references that are used to refer to memory locations, and so they save the programmer the tedious job of keeping track of addresses. An assembly language program is written so that labels, mnemonics, operands, and comments are arranged neatly in tabulated columns, that is,

[label]    [mnemonic]    [operand(s)]        ;[comment]

Each column must be separated by at least one whitespace character, and comments are preceded by a semicolon. Most assemblers are known as two pass because they parse the source code twice, first to build a table of symbolic references and associated addresses (called the symbol table) and again to produce the object code.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.129.148.210