https://quantum5.ca/2017/10/19/arm-ways-to-return/ Quantum [ ] ProjectsDMOJAbout Guanzhong ARM Assembly: [?] Ways to Return Oct 19, 2017 Code 3 minutes Quantum qt.ax/aar ARM is unusual among the processors by having the program counter available as a "general purpose" register. Most other processors have the program counter hidden, and its value will only be disclosed as the return address when calling a function. If you want to modify it, a jumping instruction is used. For example, on the x86, the program counter is called the instruction pointer, and is stored in eip, which is not an accessible register. After a function call, eip is pushed onto the stack, at which point it could be examined. Return is done through the ret instruction which pops the return address off the stack, and jumps there. Another example: on the MIPS, the program counter is stored into register 31 after executing a JALR instruction, which is used for function calling. The value in there can be examined, and a return is a register jump JR to that register. ARM's unusual design allows many, many ways of returning from functions. But first, we must understand how function calls work on the ARM. On ARM, the program counter is register 15, or r15, also called pc. The instruction to call a function is bl (for immediate offsets) or blx (for addresses in registers). These instructions stores the return address in r14, called the link register, or lr. To return, we must put this value back into pc. Method 1 When writing non-leaf functions, i.e. functions that calls other functions, the value of lr must be preserved, since calling another function will overwrite it. The most common way is to store it on the stack. On the ARM, there are convenient instructions push and pop which pushes and pops multiple values onto the stack. We typically use this to preserve the registers we modify. For example, if we want to preserve r3, r4, and lr, we can write push {r3, r4, lr}. A normal function will look like: push {r3, r4, lr} ; Save registers. ; Function body. pop {r3, r4, pc} ; Restore registers and return. This is our first way of returning: using push to restore all the registers, except putting what was lr when we are doing push into pc. This will overwrite pc with the return address, achieving the return. Note that we could instead use r14 instead of lr and r15 instead of pc, but this is less clear on the intent. Method 2 We can use an unconditional jump to register to return, which is useful in leaf functions where lr is never stored on the stack. This is simply: bx lr This jumps to the address in lr, setting pc to lr, and completing the return. Method 3 Similar in rationale to method 2, but as stated in the beginning, ARM lets you manipulate the program counter as you would any other register. So... we have: mov pc, lr This copies lr into pc, also completing the return. Method 4 To really get the point across, we can also use bitwise instructions to return. For example: orr r15, r14, r14 This performs a bitwise OR of r14 (lr) with itself, which results in the value of lr, and stores this in r15 (pc). This also copies lr into pc, completing the return. Method n Of course, there are many other ways of copying the value in one register into another, and to list that would be fairly silly. But as long as lr at the beginning of the function call is placed into pc, a return is completed. But please, use the most sensible ways to return. This means you should prefer the first two, depending on whether the function is a leaf. As a distant third, use method 3 (mov pc, lr). You may also be interested in... Using Unordered Data Structures on C++ std::pair C++'s std::pairs are not hashable by default and thus cannot be used in unordered data structures. Here's a quick fix. April 05, 2019 Optimize MySQL/MariaDB Queries with STRAIGHT_JOIN Sometimes, MySQL/MariaDB queries with many joins run insanely slowly. Using STRAIGT_JOIN might help. November 04, 2018 Python 2 on Windows: Unicode Command Lines with subprocess On Windows, using Python 2's subprocess module to launch a process with a unicode command line proves difficult. Here's a solution. July 26, 2018 Please enable JavaScript to view the comments powered by Disqus. About me My name is Guanzhong Chen, also known by my username, quantum. I am a software engineering student at the University of Waterloo, and co-founder of DMOJ, the most popular programming contest platform in Canada. * [email protected] * quantum5 * quantum5 * quantum * 3DC5 5F49 1A67 0BED * RSS Feed Support me If you like my content and would like to show your appreciation, feel free to support me and offset some of my costs: * quantum5 * quantum5 * quantum2048 Categories * Code * Desktop * Electronics * Science * Security * Sysadmin * Year Review Archives * 2023 * 2022 * 2021 * 2020 * 2019 * 2018 * 2017 Copyright (c) 2017 - 2023 Guanzhong Chen. All Rights Reserved.