In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-03-27 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article mainly introduces "how to use ARMv8 assembly instructions adrp and adr". In daily operation, I believe many people have doubts about how to use ARMv8 assembly instructions adrp and adr. Xiaobian consulted all kinds of materials and sorted out simple and easy-to-use operation methods. I hope it will be helpful to answer the doubts about "how to use ARMv8 assembly instructions adrp and adr". Next, please follow the editor to study!
1. Overview
When reading Linux kernel code, we often encounter assembly code, and the information that can be looked up on the Internet is the same, and most of them are described vaguely. As the saying goes, practice is the only criterion for testing truth, so we refer to the official documents, write our own assembly code and disassemble it, and explore the secret of it.
2.adrp
In the Linux kernel startup code primary_entry, the adrp instruction is used to obtain the starting page address of the Linux kernel in memory, and the page size is 4KB. Because the MMU is not opened when the kernel is started, the starting page address of the acquired Linux kernel in memory is the physical address. Adrp calculates the destination address by the offset address of the current PC address, which has nothing to do with the actual physics, so it belongs to the location independent code. For the specific calculation process, the following slowly analysis.
[arch/arm64/kernel/head.S] SYM_CODE_START (primary_entry). Adrp x23, _ _ PHYS_OFFSET and x23, x23, MIN_KIMG_ALIGN-1 / / KASLR offset Defaults to 0 .SYM _ CODE_END (primary_entry) [arch/arm64/kernel/head.S] # define _ _ PHYS_OFFSET KERNEL_START / / physical address of the kernel [arch/arm64/include/asm/memory.h] / / the starting and ending addresses of the kernel are defined in the vmlinux.lds link script # define KERNEL_START _ text / / the starting address of the kernel snippet That is, the starting address of the kernel is # define KERNEL_END _ end / / the end address of the kernel is 2.1. Define
The adrp instruction calculates the destination page address based on the offset address of the PC. First of all, adrp shifts a 21-bit signed immediate number to the left 12 bits to get a signed number of 33 bits (the highest bit is the sign bit), then zeros the lower 12 bits of the PC address, so as to get the address of the page where the current PC address is located, and then adds the address of the page where the current PC address is located to the signed number of 33 bits, and finally writes the target page address to the general register. The page size here is 4KB, just to get a larger address range, regardless of the page size of virtual memory. Through the adrp instruction, you can get an address in the range of the current PC address ±4GB. The usual usage scenario is to obtain a base address through adrp, and then obtain the address of a specific variable through the offset address of the base address.
The following is the encoding format of the adrp instruction. The immediate number occupies 21 bits, and at run time, the 21-bit immediate number is expanded to 33-bit signed number. The highest bit is 1, indicating that this is an aarch74 instruction.
2.2. test
The Linux kernel startup code is not easy to test, so you need to write a simple test code. The following is the test code of this adrp. Use the adrp instruction to obtain the base address of the page where the g_val1 and g_val2 arrays are located, and print the address of the array and the address of the calling function. Because it is an application layer program, these addresses are all virtual addresses, but the calculation process is the same.
# define PAGE_4KB (4096) # define _ stringify_1 (x...) # x#define _ stringify (x...) _ stringify_1 (x) uint64_t gval1 [page _ 4KB / sizeof (uint64_t)]; uint64_t gval2 [page _ 4KB / sizeof (uint64_t)]; # define ADRP (label) ({\ uint64_t _ adrp_val__ = 0 \ asm volatile ("adrp% 0," _ stringify (label): "= r" (_ _ adrp_val__));\ _ _ adrp_val__;\}) static void adrp_test () {printf ("g_val1 addr 0x%lx, adrp_val1 0x%lx, adrp_test addr 0x%lx\ n", (uint64_t) g_val1, ADRP (g_val1), (uint64_t) adrp_test) Printf ("g_val2 addr 0x%lx, adrp_val2 0x%lx, adrp_test addr 0x%lx\ n", (uint64_t) g_val2, ADRP (g_val2), (uint64_t) adrp_test);}
The output of the above program is as follows: the addresses of g_val1 and g_val2 are 0x5583e25028 and 0x5583e26028, respectively. The page base address of gambival1 is 0x5583e25000, and the base address of the 2 pages is 0x5583e26000 adrpendtest function is 0x5583e1479c.
G_val1 addr 0x5583e25028, adrp_val1 0x5583e25000, adrp_test addr 0x5583e1479cg_val2 addr 0x5583e26028, adrp_val2 0x5583e26000, adrp_test addr 0x5583e1479c
The disassembly code is shown below. The following analysis of the g_val1 page base address calculation process, including compile time and run time, g_val2 page base address calculation process is similar, I will not repeat it here.
Clear the low 12 bits of the g_val1 address to get 0x1100, clear the low 12 of the address of the current adrp instruction to get 0x0 (complete at compile time)
0x1100 minus 0x0 to get the offset address 0x11000, shift the offset address to the right 12 bits to get the number of offset pages 0x11, save the immediate count 0x11 to the instruction encoding (complete at compile time)
Take out the immediate number of 0x11, move 12 bits to the left to convert the number of bytes into offset, that is, 0x11000 (runtime completion)
Clear the lower 12 bits of the PC address to get 0x5583e14000 (runtime completion)
Add 0x5583e14000 to 0x1100 to get the g_val1 runtime page base address 0x5583e25000 (runtime completion)
000000000000079c: / / the runtime address is 0x5583e1479c. 7b0: b0000080 adrp x0, 11000 / / get the g_val1 page base address. 7e0: d0000080 adrp x0, 12000 / get the g_val2 page base address Disassembly of section .data: / / data segment definition 0000000000011000: / / the runtime address is 0x5583e25000 .disassembly of section .bss: / / bss segment definition 0000000000011028: / / the runtime address is 0x5583e25028. 0000000000012028: / / the runtime address is 0x5583e26028.
As you can see from the above, the addresses at compile time and run time are not the same, but both the g_val1 page base address and the g_val2 page base address can be correctly obtained through the adrp instruction. It indicates that the address obtained by adrp is location-independent, and the page base address of the corresponding variable can be obtained correctly no matter how the address changes at run time. Of course, we can also use professional disassembly tools to directly convert machine code into assembly code. The assembly code for the conversion of the above two adrp instructions is as follows, and as above, the offset address has been moved 12 bits to the left.
3.adr3.1. Define
The adr instruction calculates the destination address based on the offset address of the PC. The offset address is a 21-bit signed number, plus the current PC address to get the destination address. Adr can obtain addresses within the range of the current PC address ±1MB. The following is the encoding format of the adr instruction. Take up 21 digits immediately.
3.2. test
The following is the test code, which uses the adr instruction to get the addresses of the variables g_val3 and g_val4, and compares them with the addresses obtained through &.
Uint64_t g_val3 = 0tint64utt g_val4 = 0 positives define ADR (label) ({\ uint64_t _ adr_val__ = 0;\ asm volatile ("adr% 0," _ _ stringify (label): "= r" (_ _ adr_val__));\ _ _ adr_val__ Static void adr_test () {printf ("g_val3 addr 0x%lx, adr_val1 0x%lx, adr_test addr 0x%lx\ n", (uint64_t) & g_val3, ADR (g_val3), (uint64_t) adr_test) Printf ("g_val4 addr 0x%lx, adr_val2 0x%lx, adr_test addr 0x%lx\ n", (uint64_t) & g_val4, ADR (g_val4), (uint64_t) adr_test);}
Here are the test results, where the address obtained using & is the same as the address obtained through adr.
G_val3 addr 0x5583e25018, adr_val1 0x5583e25018, adr_test addr 0x5583e14810g_val4 addr 0x5583e25020, adr_val2 0x5583e25020, adr_test addr 0x5583e14810
The following is the disassembled code. As you can see, the offset address in the adr assembly code is replaced by the symbolic address used by objdump, instead of the real offset address. The real offset address of g_val3 is 0x107f4 and the real offset address of gourmet val4 is 0x107cc. If the PC address of the first adr instruction is 0x5583e14824, then 0x5583e14824+0x107f4=0x5583e25018 is the address of g_val3. The calculation process of g_val4 is similar, so I won't repeat it.
0000000000000810: / / the running address is 0x5583e14810. 10083fa0 adr x0, 11018 / / offset address is 0x11018-0x824=0x107f4. 854: 10083e60 adr x0, 11020 / / offset address is 0x11020-0x854=0x107cc.isassembly of section .data: 00000000011000: .Disassembly of section .bss: .0000000000011018: / / run address is 0x5583e25018... 00000000011020: / / run address is 0x5583e25020.
At this point, the study on "how to use ARMv8 assembly instructions adrp and adr" is over. I hope to be able to solve your doubts. The collocation of theory and practice can better help you learn, go and try it! If you want to continue to learn more related knowledge, please continue to follow the website, the editor will continue to work hard to bring you more practical articles!
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: 246
*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.