ARM assembly tutorial (2): Data types and registers

Publisher:书香门第Latest update time:2022-12-09 Source: zhihuKeywords:ARM Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

type of data

This is the second part of a series of tutorials on ARM assembly basics, covering data types and registers.

Similar to high-level languages, ARM supports operations on different data types. The data types we can load (or store) can be signed and unsigned words, halfwords, or bytes. The extensions to these data types are. -h or -sh for halfwords, -b or -sb for bytes, and words without extension. The difference between signed and unsigned data types is.

Signed data types can accommodate both positive and negative values ​​and therefore have a smaller range.

Unsigned data types can hold large positive values ​​(including "zero"), but not negative values, so they have a wider range.

Below are some examples of how these data types are used with the Load and Store instructions.

Big and small endian

In memory, there are two basic ways of looking at bytes. Little endian (LE) or big endian (BE). The difference is the order in which each byte of an object is stored in memory. On little-endian machines like Intel x86, the least significant byte is stored at the lowest address (the address closest to zero). On big-endian machines, the most significant byte is stored at the lowest address. The ARM architecture was little-endian until version 3, and since then it has been dual-endian, meaning it has a setting that allows for switchable endianness. For example, in ARMv6, instructions are fixed little endian and data accesses can be little endian or big endian, controlled by bit 9 (E bit) of the Program Status Register (CPSR).

ARM register

The number of registers depends on the ARM version. According to the ARM reference manual, there are 30 general-purpose 32-bit registers except for ARMv6-M and ARMv7-M based processors. The first 16 registers are accessible in user-level mode, and the other registers are available in privileged software execution (except for ARMv6-M and ARMv7-M). In this series of tutorials, we will deal with a register that is accessible in any privileged mode: r0-15. These 16 registers can be divided into two groups: general-purpose registers and special-purpose registers.

The following table shows the relationship between ARM registers and registers in Intel processors.

R0-R12: Can be used to store temporary values, pointers (memory locations), etc. in normal operations. For example, R0 can be used as an accumulator when performing arithmetic operations, or to store the results of previously called functions. R7 becomes very useful when handling system calls as it stores the number of the system call and R11 helps us keep track of boundaries on the stack as frame pointers (to be covered later). Additionally, ARM's function calling convention states that the first four parameters of a function are stored in registers r0-r3.

R13: SP (stack pointer). The stack pointer points to the top of the stack. The stack is an area of ​​memory used for specific function storage and is reclaimed when the function returns. Therefore, the stack pointer is used to allocate space on the stack by subtracting the value we want to allocate (in bytes) from the stack pointer. In other words, if we want to allocate a 32-bit value, we subtract 4 from the stack pointer.

R14: LR (link register). When a function is called, the link register is updated with the memory address referencing the next instruction initiated by the function. Doing this allows the program to return to the "parent" function that started the "child" function after the "child" function has completed.

R15: PC (program counter). The program counter is automatically incremented based on the size of instructions executed. This size is always 4 bytes in ARM state and 2 bytes in THUMB mode. When a branch instruction is executed, the PC saves the target address. During execution, the PC stores the address of the current instruction plus 8 (two ARM instructions) in the ARM state, and stores the address of the current instruction plus 4 (two Thumb instructions) in the Thumb (v1) state. This is different from x86, where the PC always points to the next instruction to be executed.

Let's see how the PC behaves in the debugger. We use the following program to store the address of the PC into r0 and include two random instructions. Let's see what happens.

In gdb we set a breakpoint at _start

The following is the result of the operation:

We can see that PC holds the address (0x8054) of the next instruction that will be executed (mov r0, pc). Now let's execute the next instruction, after which R0 should hold the address of PC (0x8054), right?

...Is it right? wrong. Look at the address in R0. While we expected R0 to contain the PC value we read previously (0x8054), it instead contains a value two instructions ahead of the PC value we read previously (0x805c). You can see from this example that when we read the PC directly, it follows the definition that the PC points to the next instruction; but when debugging, the PC points to two instructions before the current PC value (0x8054 + 8 = 0x805C). This is because older ARM processors always fetch two instructions before the currently executing instruction. The reason ARM retains this definition is to ensure compatibility with earlier processors.

Current program status register

When you use gdb to debug an ARM binary, you will see something called Flags.

Register $cpsr shows the value of the current program status register (CPSR). Below it you can see Flagsthumb, fast, interrupt, overflow, carry, zero, and negative. These flags represent certain bits in the CPSR register and are set based on the value of the CPSR, turning bold when activated. The N, Z, C, and V bits are the same as the SF, ZF, CF, and OF bits in the EFLAG register on x86. These bits are used to support assembly-level conditionals and conditional execution of loops. We'll cover using conditional code in Part 6, "Conditional Execution and Branching."

The figure above shows the layout of a 32-bit register (CPSR), with the left (<-) being the most significant bits and the right (->) being the smallest bits. Each unit (except the GE and M parts and the blank part) is one bit in size. These one-bit portions define various properties of the current state of the program.

Let us assume that we use CMP instruction to compare numbers 1 and 2. The result is "negative" because 1-2=-1. When we compare two equal numbers, say 2 versus 2, the Z (zero) flag is set because 2-2=0. Remember that the registers used by the CMP instruction are not modified, only the CPSR is modified based on the results of comparing these registers with each other.

This is the case in GDB (with GEF installed). In this example, we compare registers r1 and r0, where r1=4 and r0=2. This is the situation of the flag after executing the cmp r1, r0 operation.

The carry flag is set because we used cmp r1, r0 to compare 4 and 2 (4-2). Conversely, if we use cmp r0, r1 to compare a smaller number (2) with a larger number (4), the negative flag (N) is set.

Here is an excerpt from the ARM Information Center:

APSR contains the following ALU status flags.

N - Set when the result of the operation is negative.

Z - Set when the result of the operation is zero.

C - Set when the result of the operation is a Carry.

V--Set when the operation causes overflow.

carry is set when:

If the result of addition is greater than or equal to 2^32

If the result of subtraction is positive or zero

As a result of an inline shift operation in a move or logic instruction.

If the result of addition, subtraction, or comparison is greater than or equal to 2^31, or less than 2^31, an overflow occurs.

This article is the second part of the ARM assembly tutorial series. It introduces the basic data types of arm and basic register related knowledge.


Keywords:ARM Reference address:ARM assembly tutorial (2): Data types and registers

Previous article:ARM assembly tutorial (3): ARM instruction set
Next article:ARM Assembly Tutorial (1): Introduction to ARM Assembly

Recommended ReadingLatest update time:2024-11-16 16:03

Temperature sensor driver based on ARM-LINUX (DS18B20)
The DS18B20 digital temperature sensor is easy to wire and can be used in a variety of occasions after packaging, such as pipeline type, threaded type, magnet adsorption type, stainless steel package type, and various models, including LTM8877, LTM8874, etc. Its appearance is mainly changed according to different appl
[Microcontroller]
Temperature sensor driver based on ARM-LINUX (DS18B20)
ARM's seven exception sources and exception handling process (four major steps and three small steps)
                                                     ARM exception handling (processor's handling of specific exception events) entry process (automatically completed by hardware): Four major steps (two backups and two modifications) and three minor steps: (1) Copy CPSR (current program status register) to SPSR_
[Microcontroller]
ARM's seven exception sources and exception handling process (four major steps and three small steps)
Arm: Most products are not subject to US export controls
Arm CEO Simon Segars said that most of our products are not subject to US export controls, and this will not change with the change of US parent company. Nvidia released a statement today, officially announcing that it will acquire Arm from SoftBank for $40 billion. According to the agreement, Nvidia will pay SoftBank
[Mobile phone portable]
ARM commonly used pseudo instructions
1. AREA  The AREA directive is used to define a code segment or a data segment.        Syntax format:         AREA segment name attribute 1, attribute 2, ...         If the segment name starts with a number, the segment name must be enclosed in “|”, such as |1_test|.         The attribute field indicates the relevant
[Microcontroller]
ARM Linux kernel layout in memory
Kernel Memory Layout on ARM Linux Russell King rmk@arm.linux.org.uk      November 17, 2005 (2.6.15) This document describes the virtual memory layout which the Linux kernel uses for ARM processors.  It indicates which regions are free for platforms to use, and which are used by generic code. The ARM CPU is c
[Microcontroller]
ARM9_S3C2440 learning (V) norflash startup, nandflash startup, SDRAM summary
The first instruction read when S3C2440 starts is at 0x00, which is divided into starting on nand flash and nor flash.   NAND flash: suitable for large-capacity data storage, similar to hard disk; nor flash: suitable for storing small-capacity programs or data, similar to a small hard disk; sdram: Mainly used for prog
[Microcontroller]
Mixed C and assembly programming in ARM and examples
Parameter passing rules. Depending on whether the number of parameters is fixed, subroutines can be divided into subroutines with fixed number of parameters and subroutines with variable number of parameters. The parameter passing rules of these two subroutines are different. 1. Parameter passing rules
[Microcontroller]
Design and implementation of MP3 player based on ARM
Abstract: In order to overcome the shortcomings of the current MP3 in the market, such as small storage capacity, high price, complex operation, and single song playback, an MP3 player based on ARM LPC2131 is designed. The player is mainly composed of two parts: audio decoding module and music file access module. Th
[Industrial Control]
Design and implementation of MP3 player based on ARM
Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号