This series of study notes is based on 32-bit ARM, leaving out ARM64 and 16-bit Thumb mode

The notes blogger took the class notes of embedded System of XDIAN university one year ago. The blogger is not in the direction of embedded system and does not plan to do embedded development. He just learned to play with it

ARM operating mode

ARM has three categories and seven operating modes. You can switch between them as required

  • USR: User mode, running user code. All other modes are privileged
  • SYS: system mode, running the operating system code
  • Exception mode: a mode entered when a program cannot continue execution for any reason
    • FIQ: Fast interrupt, used for high-speed data transmission
    • IRQ: External interrupt, used for normal interrupt handling
    • SVC: Administrative mode, protected mode for the operating system (high privilege), reset and soft interrupt access
    • ABT: Abort, data access Abort mode, when data or instruction prefetch terminates, can be used for virtual memory, storage protection
    • Und: Directive does not define abort. This exception can be used to handle the situation of unknown instructions. When encountering an unknown instruction, the program will jump to the exception handler to avoid running away. It can also be used to customize instructions, support coprocessors, and more

The CPU’s finger-decode-execute cycle

As long as the CPU is running properly, it will always execute the finger-decode-execute process. The process can be divided into three modes:

  • Sequential execution: finger-decode – execute -> Remove next instruction – decode – execute……
  • Jump:
    • Subfunction call: jumps to another location to execute an instruction, which returns to the location it skipped
    • Branch: No return after a jump
  • Interrupt: Jumps to an interrupt service routine after executing the currently executing instruction. After completing the interrupt service procedure, return to the original position of the next instruction to continue execution. (Interrupt service routines can do a lot of things, such as paging virtual memory — so the programmer doesn’t feel the paging.)

ARM register

The register is the space inside the CPU that is directly connected to the ALU via the internal bus.

ARM e has 37 registers in total, which is much richer than x86.

  • 31 * General purpose register

    • R0 to R14 and PC are visible to all modes (ARM can operate on PC)
      • R0 to R7 This parameter is shared by all modes and can be used when switching states
      • R13 is the stack pointer (SP) that points to the top of the current stack. Each exception has its own SP, which means that each exception can have its own stack
      • R14 is the link register (LR), which automatically saves the return address in the event of an exception
    • R15 is also a general-purpose memory, but is generally used as a PC. If you want to go anywhere, you can just write to R15, which is very convenient.
    • R13 and R14 for USR and SYS are independent of R13_SVC and R14_SVC for SVC. Therefore, these registers can be used to replace the stack when jumping, so as to realize on-site protection.)
  • 6 * Status register

    • 1 * CPSR (Current Program State Register) : It is the same as PSW

    • 5 * Saved Program Status Register (SPSR) : Each exception has its own SPSR. The SPSR is used to save the CPSR value when the exception is processed, so that the original working Status can be returned after the exception is processed

ARM instruction system

ARM is a Load/Store processor that can operate only in registers, not in memory. When used, values are read from memory to register, and then put back after calculation

Instructions can be divided into several categories: data processing, Load/Store (register, memory data transfer), jump, CPSR processing, exception generation, and coprocessor

Addressing mode

  • Immediate addressing (immediate digital addressing) : Operands are placed directly in the instruction stream

  • Register addressing: Removing register values

  • Register shift addressing: MOV R0, R2, LSL #3 R2 values move logically left 3 bits to send R0 (immediately start with #)

  • 2. To place a value in memory using a register value as the address of memory, as in:

    LDR R0, [R1] @ R1 address value read to R0 STR R0, [R1] @ R0 register value written to address R1Copy the code
  • Variable addressing: Memory can be read using base address + offset as address value

    LDR R0, [R1, #4] @ the offset is the immediate number LDR R0, [R1, R2] @ the offset is the register value LDR R0, [R1, R2, LSL#2] @ the offset is R2Copy the code
  • Relative addressing: Use PC as the base address register for variable addressing

  • Block copy addressing

  • Stack addressing

ARM assembly

It’s a bit messy, and since I don’t want my notes to be a dictionary, I’m going to write down some code examples instead of the ubiquitous manual explanations

@ Common format: <opcode>{<cond>}{S} <Rd>, <Rn>, {, {oprand2}} @opcode is the instruction, cond is the instruction condition such as EQ, ne@ Rd is the target register, Rn is the register where the first operand is. @oprand2 is the second operand, which can be either a register or an immediate number. ADD R2, R1, R0 @ ADD, and R1+R0 ADDS to ADDS R1, R1, #1 @ ADD, and the immediate number 1 as the second operand: R1+1 results send R1. @s stands for operation influence CPSR (well, ARM's PSW can be manually controlled in this way) BEQ DATAEVEN @b is jump, EQ is condition Equal. DATAEVEN is the destination position SUBNES R1, R1, # 0x0d@sub: subtraction; NE: NotEq; S: Results affect CPSR. R1mov R0, R2, LSL # 3@r2, R0 MOV R0, R2, LSL # 3@r2 So it's R2 times 8 ADD R3, R2, LSR R4 times R2 move it to the right by the median of R4, and it goes to R3Copy the code

What else are ADC with carry plus, SBC with borrow minus, AND bitwise AND, ORR bitwise or, EOR xOR, TST bitwise AND, TEQ bitwise or

LDR, STR single register whole word (word, 32-bit) access, STRH half word (half-word, 16-bit), STRB byte (8-bit)

LDM, STM multi-register access, LDMFD R0! , {r1-r4} Four consecutive memory units starting with [R0] write r1-r4, which can be done by writing! Note Write back is required. Copy SPSR to CPSR by adding ^ to {r1-r4}

SWP exchanges data between two registers. This can be used for synchronization and mutual exclusion between processes

MRS, MSR: CPSR, SPSR and general register Rn write each other. Such as:

  • MRS R0, CPSRSend the CPSR R0
  • MSR R0, SPSRSend the R0 SPSR

jump

There are two ways to jump. One is to directly write the target address value to PC (R15), which can jump the space before and after 4GB.

Second, use the following jump instruction (the range is 32MB space before and after the current instruction)

  • B you jump
  • BL with return hops, the current PC value will be sent to R14 before jumping away, and then back again
  • BX with state switch, can realize ARM, Thumb mode switch
  • BLX L and X has the same meaning as the first two

Pseudo operation and pseudo instruction

Actually the pseudo instruction is contained in the pseudo operation. Both are for the assembler. The dummy is written to the assembler along with the actual assembly, but the assembler will process the dummy during assembly, giving the actual machine instructions or sequence of instructions

Pseudo-operations can be used to define symbols, define data, control, report information (for errors in assembly, etc.), do section definitions, specify code types, define program entry points, and so on

I’m going to write it in a dictionary, so I’m going to write a couple of big examples

Find the greatest common divisor:

AREA GCD, CODE, READONLY @ Defines the CODE ENTRY @ identifies the program ENTRY point. A source file has at most one ENTRY. If there are multiple entries, the linker must specify the ENTRY start CMP R0, R1 @ label start and instruction sequence. So if BEQ stop @ is equal, we'll skip to stop, so we can branch BLT less @ is less than SUB R0,R0,R1 B start @ jumps back, Less SUB R1, R1, R0 B start @ jump back to start a new loop stop NOP @ null operation, does not impact CPSR MOV PC, LR END @ specify the END of segmentCopy the code

AREA GCD, CODE, READONLY defines the CODE snippet for this small program. ARM assembler organizes source files in segments, a segment being a relatively independent sequence of instructions/data with a specific name. Multiple segments are compiled and linked to form an executable image file. This file contains at least one code segment, which can have zero or more data segments with or without initialization data

ARM abnormal interrupt processing

When the CPU is running properly, the PC value increases by 4 for each instruction executed (i.e., moves 32 bits back to the next instruction)

Abnormal interrupt: After executing the current command, protect the site and jump to the abnormal interrupt handler (THE CPU jumps to the address of the corresponding exception handler in the abnormal direction table by changing the PC value). The handler completes execution, then returns to the position before the interruption, resumes the scene and continues execution

Types and sources of exceptions:

  • Reset: The Reset pin is valid
  • Undefined Instruction: read Instruction that cannot be decoded
  • SWI (Software Interrupt) : An exception caused by an instruction
  • Instruction Prefetch, DataAbort: when fetching a number or finger, the expected value is not fetched
  • External interrupt (IRQ), fast interrupt (FIQ) : valid from the pin

The vector table is the entry address of the exception. When the corresponding exception occurs, the CPU will jump to the corresponding vector address, and then jump to the exception processing address in the vector address to realize the exception processing.

The anomaly direction table generally has the lowest part of the address, which is distributed as follows

address abnormal
0x00 reset
0x04 undefined
0x08 SWI
0x0c Prefetch
0x10 DataAbort
0x14 NOP
0x18 IRQ
0x1c FIQ

0x00 is also the first address that the CPU reaches when the system is powered on

Response and return steps

The response

  1. The CPSR is stored in the CORRESPONDING SPSR. This SPSR refers to the interrupt-mode SPSR to jump to. For example, to jump from USR to FIQ, send the user-mode CPSR to FIQ’s SPSR
  2. Reset each CPSR field value to realize the CPU switch to the corresponding mode, such as FIQ mode bit is 10001, and then you can use the independent register in this mode
  3. Store the return address into the LR of the corresponding schema
  4. Set PC as the interrupt vector address to achieve forced jump

return

  1. Example Restore the CPSR from the SPSR

  2. The LR value minus the offset is sent to the PC (the offset is reduced because the hardware may not have time to adjust the address when the exception comes. Here are some exceptions and the corresponding return locations)

    Instruction prefetch abort: LR-4

    Data abort: LR-8

    IRQ: LR – 4

    FIQ: LR – 4

    Undefined, SWI returns LR directly. (Reset does not need to return)

  3. Restore each register value according to the actual situation

Jump (Set direction table)

You can usually jump with B, but if you want to jump far, you have to write PC

AREA boot, CODE, READONLY ENTRY LDR PC, reset_Add@ Interrupt direction table LDR PC, undefined_add@... LDR PC, FIQ_Add Reset_Add DCD Start_Boot @ interrupt handler entry, put in memory @ DCD: allocate a contiguity of space and initialize @ meaning: Undefined_Add DCD Undefined_Handler @... FIQ_Add DCD FIQ_Handler Start_Boot @... The code that does the actual processing, that is, the interrupt handler implements undefined_handler@... The code that does the actual processing fiq_handler@... The code that does the actual processingCopy the code

Example of an actual interrupt handler: IRQ_Handler

This can be used as a template, and the other interrupt handling is to change the function called (right?).

EXPORT irq_handler@export, declare the global label, the whole program visible, AREA IRQ_Handler, CODE, READONLY SUB LR, LR, #0x4 @ Set return address to LR-4 STMFD SP! , {r0-r12, LR} @ register pressing, protect the scene. R4, spsr@spsr, R4 STMFD SP! , {R4} @push, R4 store to the memory location pointed by SP (i.e. the top of the stack) BL IRQ_Function @ jump to the real interrupt handling child function LDMFD SP! , {R4} @restore MSR SPSR_cxsf, R4 @ CXSF refers to four 8-bit fields, here is the entire 32-bit register LDMFD SP! , {r0-r12, PC}^ @ Restore the scene and return ENDCopy the code