Embedded Systems/Assembly Language
This book will demonstrate techniques for programming embedded systems in assembly language.
x86 Assembly Review
The x86 microprocessor has (at least):
- 4 general purpose registers
- AX, BX, CX, and DX. AX is the fast accumulator.
- 4 segment registers
- CS (code section), DS (data section), ES (extra section), SS (stack section).
- 5 pointer registers
- SI (source index), DI (destination index), IP (instruction pointer), SP (stack pointer), BP (base pointer).
- 1 flag register
- Flags ('7' flags like Zero flag, Carry flag)
Unlike "memory-mapped" processors, the x86 has special "I/O" instructions (inp, outp) intended to talk to I/O hardware.
ARM assembly review
At any one time, 17 registers can be accessed: R0 to R14 (which have identical hardware), R15, and the status register CPSR.
(To reduce latency on interrupt handling, these registers and the SPSR "saved program status register" are "shadowed" during interrupts. Including those shadows, the typical ARM processor has a total of 37 registers).
The standard C calling convention for ARM is:
- R15: PC: program counter
- R14: LR: link register (holds return address for most recent subroutine call)
- R13: SP: stack pointer (for nested subroutine calls)
- R12-R4: long-term variables: used by a subroutine only if it restores the original values before it returns
- R3-R0: scratch-pad variables and subroutine-call parameters and subroutine-return results.
I/O hardware is typically "memory mapped".
Motorola/Freescale HCS12 (Star 12) Review
- 16-bit accumulator register
- D, accessible as two 8-bit registers: A (high) and B (low)
- 2 16-bit index registers
- X, Y
- 16-bit stack pointer register
- 16-bit program counter
- 8-bit condition code register
The HCS12 is based on the older 68HC11 and the instruction sets are very similar. The HCS12 is a "Big Endian" processor: multi-byte values are stored from most significant byte to least significant byte in increasing memory addresses.
Modern desktop PCs are almost all 32 bit machines, and the next generation of processors is going to be fully 64 bit. This is all well and good for the average programmer, but what do you do when you are in an embedded situation with a microcontroller the size of your finger nail that is capable of only 4 bit arithmetic? 32 bits may be the norm in the desktop market, but there is no gold standard in embedded chips: more bits take up more space and costs more money. In essence, it is the job of a good embedded systems engineer to find the smallest, cheapest microcontroller that does the job that needs to get done. Consider the following table:
bits biggest unsigned number biggest signed number smallest signed number* 4 15 7 -8 8 255 127 -128 16 65,535 32,767 -37,768
- * 2's complement format
Even the 16 bit processor is a far cry from the 4 billion integer range of a standard 32 bit processor. Let's say that we have a 4 bit microcontroller with 4 available internal registers (4 bit each), and 256 bytes of onboard programmable memory. This processor cannot handle anything but the most simple tasks! What if we need to manipulate an 8-bit number on this little microprocessor? for instance, what if we want to make a digital clock with it? the 4 bit microprocessor is going to need to handle numbers up to and including 59 (the number of minutes displayed before the next hour). This is going to require more than the 4 bits alotted, in fact it is going to require at least 6 bits of space. What we need to do then, is come up with a way to treat 2 separate small registers as if they are a single large register. This chapter will talk about that subject a little bit.