In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-03-28 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
This article introduces the relevant knowledge of "how to learn ARM assembly pseudo instruction LDS from 0". In the operation of actual cases, many people will encounter such a dilemma, so let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!
I. the difference between MDK and / GNU pseudo instructions
When we learn the assembly code, we will see the following two styles of code:
The gnu code begins with:
.global _ start _ start: @ assembler entry ldr sp,=0x41000000 .end @ assembler ends
The MDK code begins with:
AREA Example,CODE,READONLY; declare code snippet Example ENTRY; program entry Start MOV R0 OVER END
These two styles of code use different compilers, and our previous example code is MDK-style.
So much for us beginners to learn which style? The answer is yes, learn GNU style assembly code, because to do Linux driver development must master the linux kernel, uboot, and these two software is GNU style.
In order not to waste too much energy on temporarily useless knowledge, let's just talk about GNU style compilation.
2. GNU assembly writing format:
1. Comment symbols in lines of code:
The whole line comment symbol: the'# 'statement separates the symbol:
Direct Operand prefix:'#'or'$'
two。 Global label:
The label can only be made up of characters such as ".", ".", etc. (composed of dots, letters, numbers, underscores, etc., which can not start with numbers except local labels), followed by ":".
The address value of the label within the segment is determined at the time of assembly; the address value of the label outside the segment is determined at the time of connection.
3. Local label:
The local label is mainly used in the local scope and the local label can be repeated. It consists of two parts, beginning with a 0-99 direct number followed by a local label ":"
F: instructs the compiler to search only forward, the direction in which the number of lines of code increases / the next sentence of the code B: instructs the compiler to search only backward and the direction in which the number of lines of code decreases
Pay attention to the jump of local labels, the nearest principle "for example:"
File location arch/arm/kernel/entry-armv.S
3. Pseudo operation:
1. Symbol definition pseudo instruction
two。 Data definition (Data Definition) pseudo operation
Data definition pseudo-operations are generally used to allocate storage units for specific data, while initializing allocated storage units can be completed. Common data definition pseudo operations are as follows:
[example]
.word
Val:. Word 0x11223344 mov R1 minute Val; set the value 0x11223344 to register R1
.space
Label: .space size,expr; expr can be a floating point number within 4 bytes a: space 8, 0x1
.rept
.rept cnt; cnt is the number of repeats .endr
Note:
Hongmeng official Strategic Cooperation to build HarmonyOS Technology Community
The definition of the variable is placed after stop and before .end
The label is the mnemonic of the address, and the label does not take up storage space. The location can be in front of the end, relatively casual.
3. If selection
Grammatical structure
If logical-expressing. Else. .endif
Similar to conditional compilation in the c language.
[example]
.if val2==1 mov r1,#val2 .endif
4. Macro macro definition.
Macro,.endm macros define macrofunctions similar to those in the c language.
A macro pseudo operation can define a piece of code as a whole, called a macro instruction. The code can then be called multiple times in the program through a macro instruction.
Syntax format:
Name {$label} name {$parameter {, $parameter}... }. .. code .endm
Where the $label is replaced with a user-defined symbol when the macro instruction is expanded.
A macro action can use one or more parameters, which are replaced by the corresponding values when the macro action is expanded.
"Note": define before using
For example:
"[example 1]: the macro realization subfunction with no parameters returns"
.macro MOV_PC_LR
MOV PC,LR
.endm
The calling method is as follows: MOV_PC_LR
"[example 2]: macro implementation subfunction with parameters returns"
.resume MOV_PC_LR, param mov R1,\ param MOV PC,LR .endm
The calling method is as follows:
MOV_PC_LR # 12
IV. Miscellaneous pseudo operations
For example: .set
.set start, 0x40 mov R1, # start; R1 contains 0x40
Give an example of .equ
.equ start, 0x40 mov R1, # start; in R1 is 0x40#define PI 3.1415
Equivalent to
.equ PI, 31415
5. GNU pseudo instruction
Key point: pseudo instructions are converted to corresponding ARM instructions at compile time
1.ADR directive: this directive loads the address of the label into the register. The ADR directive reads the directive for a small range of addresses, using a relative offset range: when the local address value is byte alignment (8 bits), the range is-255mm 255, and when the local address value is word alignment (32 bits), the range is-1020mm 1020. Syntax format:
ADR {cond} register,label R R0, lable
2.ADRL directive: read medium range addresses into registers
The ADRL directive reads the directive for a medium range address. Use relative offset range: when the local address value is byte aligned, the range is-64cm 64KB; when the local address value is word aligned, the range is-256~256KB
Syntax format:
ADRL {cond} register,label ADRL R0,lable
3.LDR directive: the LDR directive loads a 32-bit constant and an address to the register. Syntax format:
LDR {cond} register,= [expr | label-expr] LDR R0 script 0XFFFF0000; mov R1 script 0x12 comparison
Note: (1) the distinction between the ldr directive and the ldr directive is the ldr directive:
Ldr R1 MDK Val @ R1 = val is a pseudo instruction that assigns the val label address to R1 [unlike MDK, MDK only supports ldr R1 camera Val]
Here is the ldr directive:
Ldr R2 val @ R1 = * val is an arm instruction that gives the contents of the labeled val address to R2 val: .word 0x11223344
(2) how to use ldr pseudo instruction to realize long jump
Ldr pc,=32 bit address
(3) arm pseudo instruction ldr is used to solve the problem of non-immediate number in coding.
Ldr r0judicial 0x999; 0x999 is not immediate.
VI. Compilation of GNU assembly
1. Compilation without lds files
Suppose we have the following code, including 1 main.c file and 1 start.s file: start.s
.global _ start _ start: @ assembly entry ldr sp,=0x41000000 b main .global mystrcopy .text mystrcopy: / / parameter dest- > r0 STRB src-> R2 LDRB R2, [R1], # 1 CMP R2, [R0], # 1 CMP R2, # 0 / / determines whether it is a string trailing BNE mystrcopy MOV pc, lr stop: B stop @ endless loop, preventing running from running is equivalent to the end of while (1) .end @ assembler.
Main.c
Extern void mystrcopy (char * dje Const char * s); int main (void) {const char * src = "yikoulinux"; char dest [20] = {}; mystrcopy (dest,src); / / call the assembly implemented mystrcopy function while (1); return 0;}
The Makefile is written as follows:
1. TARGET=start 2. TARGETC=main 3. All: 4. Arm-none-linux-gnueabi-gcc-O0-g-c-o $(TARGETC). O $(TARGETC). C 5. Arm-none-linux-gnueabi-gcc-O 0-g-c-o $(TARGET). O $(TARGET). S 6. # arm-none-linux-gnueabi-gcc-O 0-g-S-o $(TARGETC). S $(TARGETC) .c 7. Arm-none-linux -gnueabi-ld $(TARGETC). O $(TARGET). O-Ttext 0x40008000-o $(TARGET). Elf 8. Arm-none-linux-gnueabi-objcopy-O binary-S $(TARGET). Elf $(TARGET). Bin 9. Clean: 10. Rm- rf *. O *. Elf *. Dis *. Bin
Makefile has the following meanings:
Hongmeng official Strategic Cooperation to build HarmonyOS Technology Community
Define the environment variable TARGET=start,start as the file name of the assembly file
Define the environment variable TARGETC=main,main as a c language file
Target: the all,4~8 line is the instruction statement of the instruction
Compiling main.c into main.o,$ (TARGETC) will be replaced with main
Compiling start.s into start.o,$ (TARGET) will be replaced with start
4-5 can also be implemented with one instruction of this line.
Using the ld command to generate start.elf,-Ttext 0x40008000 for main.o and start.o links indicates that the starting address of the code snippet is set to 0x40008000
Convert start.elf to start.bin file through objcopy,-O binary (or-- out-target=binary) output to the original binary file,-S (or-- strip-all) output file without repositioning information and symbol information, reducing the file size
Clean goal
The execution statement of the clean target to delete the temporary files generated by the compilation
[supplement]
Hongmeng official Strategic Cooperation to build HarmonyOS Technology Community
For the code optimization level of gcc, the higher the O0-O3 number of the compilation command level 4 in the makefile file, the higher the degree of optimization. O _ 3 maximum optimization
Volatile acts as a volatile-decorated variable, and the compiler no longer optimizes it, actually accessing the memory address space each time.
two。 Rely on lds file compilation
The actual engineering file, segment complexity is much more complex than ours, especially the Linux kernel has tens of thousands of files, the distribution of segments is very complex, so we need to use lds files to define the distribution of memory.
File list
Main.c and start.s are the same as in the previous section.
Map.lds
OUTPUT_FORMAT ("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") / * OUTPUT_FORMAT ("elf32-arm", "elf32-arm", "elf32-arm") * / OUTPUT_ARCH (arm) ENTRY (_ start) SECTIONS {. = 0x40008000;. = ALIGN (4); .text: {.start.o (.text) * (.text)}. = ALIGN (4); .rodata: {* (.rodata)}. = ALIGN (4); .data: {* (.data)}. = ALIGN (4); .bss: {* (.bss)}}
Explain the above example:
Hongmeng official Strategic Cooperation to build HarmonyOS Technology Community
OUTPUT_FORMAT ("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") specifies the default binary file format for outputting object files. You can use objdump-I to list supported binary file formats
OUTPUT_ARCH (arm) specifies that the output platform is arm, and you can query the supporting platform through objdump-I.
ENTRY (_ start): sets the value of the symbol _ start to the entry address
. = 0x40008000: sets the locator symbol to 0x40008000 (if not specified, the initial value of the symbol is 0)
.text: {.start.o (.text) * (.text)}: the former means to place the start.o in the first location of the text section, and the latter means to merge the .text section of all input files (the * symbol represents any input file) into one .text section.
.rodata: {* (.data)}: merge the .rodata section of all input files into a single .rodata section.
.data: {* (.data)}: merge the .data section of all input files into one .data section
.bss: {* (.bss)}: merge the .bss section of all input files into one .bss section;. This section usually holds global uninitialized variables.
. = ALIGN (4); indicates that the following segments are 4-byte aligned
Each time the connector reads a section description, it increases the value of the locator symbol by the size of the section.
Take a look at how Makefile should write:
# CORTEX-A9 PERI DRIVER CODE # VERSION 1.0 # ATHUOR Linux # MODIFY DATE # 2020.11.17 Makefile # = = # CROSS_COMPILE = arm-none-linux-gnueabi- NAME = start CFLAGS=-mfloat-abi=softfp-mfpu=vfpv3-mabi=apcs-gnu-fno-builtin- fno-builtin-function-g-O0-c LD = $(CROSS_COMPILE) ld CC = $(CROSS_COMPILE) gcc OBJCOPY = $(CROSS_COMPILE) objcopy OBJDUMP = $( CROSS_COMPILE) objdump OBJS=start.o main.o # = = # all: $(OBJS) $(LD) $(OBJS)-T map.lds-o $(NAME). Elf $(OBJCOPY)-O binary $(NAME). Elf $(NAME). Bin $(OBJDUMP)-D $(NAME). Elf > $(NAME). Dis%. O:%. S $(CC) $(CFLAGS)-c-o $@ $<%. O:%. $(CC) $(CFLAGS)-c-o $@ $<%. O:%. C $(CC) $(CFLAGS)-c-o $@ $< clean: rm-rf $(OBJS) * .elf * .bin * .dis * .o
The compilation results are as follows:
Compilation result
Finally, the start.bin is generated, and the modified file can be burned to the development board for testing, because there is no intuitive phenomenon in this example. In the follow-up article, we will add other functions to re-test.
[note]
Hongmeng official Strategic Cooperation to build HarmonyOS Technology Community
Among them, the cross-compilation tool chain "arm-none-linux-gnueabi-" should be selected according to its own actual platform. This example is based on Samsung's exynos-4412 tool chain.
The address 0x40008000 is not chosen randomly.
Exynos4412 address distribution
Readers can look up the address according to the soc manual corresponding to the development board in their hands.
Exception Vector Table of linux Kernel
The memory distribution of the linux kernel also depends on the definition of the lds file. We will not discuss the compilation of the linux kernel for the time being. After compilation, the corresponding lds file will be generated in the following location:
Arch/arm/kernel/vmlinux.lds
Let's look at some of the contents of the file:
Vmlinux.lds
OUTPUT_ARCH (arm) formulates the corresponding processor
ENTRY (stext) indicates that the entry to the program is stext.
At the same time, we can also see that the partition of linux memory is more complex. We will discuss the linux kernel later and then continue to analyze the file.
3. The difference between elf files and bin files:
1) ELF
The ELF file format is an open standard. Executables for various UNIX systems are in ELF format, and there are three different types:
Relocatable object file (Relocatable, or Object File)
Executable file (Executable)
Shared libraries (Shared Object, or Shared Library)
The ELF format provides two different perspectives. The linker treats the ELF file as a collection of Section, while the loader treats the ELF file as a collection of Segment.
2) bin
The BIN file is a direct binary file with no address tag inside. The internal data of the bin file is arranged according to the physical space address of the code segment or data segment. Generally speaking, when writing with a programmer, it starts at 00, but if you download and run, you can download it to the address at the time of compilation.
On Linux OS, in order to run executable files, they follow the ELF format, usually gcc-o test test.c, the generated test file is in ELF format, so you can run and execute the elf file, then the kernel will use the loader to parse the elf file and execute it.
In Embedded, if you start to run on power, there is no OS system, if you burn and write files in ELF format, including some section such as the symbol table character table of ELF files, running across these, it will lead to failure, if you use objcopy to generate pure binary files, remove section such as symbol tables, and only retain the code segment data segments, the program can run step by step.
The elf file contains symbol tables and so on. The BIN file is a memory image that extracts code segments, data segments, and some custom segments from the elf file.
And the location of the snippet data segment in the elf file is not its actual physical location. His actual physical location is marked in the table.
This is the end of the introduction of "how to learn ARM assembly directives LDS from 0". Thank you for your reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.