https://eclecticlight.co/2021/06/16/code-in-arm-assembly-registers-explained/ Skip to content [eclecticlight] The Eclectic Light Company Macs, painting, and more Main navigation Menu * Downloads * M1 Macs * Mac Problems * Mac articles * Art * Macs * Painting hoakley June 16, 2021 Macs, Technology Code in ARM Assembly: Registers explained In the first article in this series on developing for Apple Silicon Macs using assembly language, I built a simple framework AsmAttic to use as the basis for developing ARM assembly language routines. In that, I provided a short and simple demonstration of calling an assembly routine and getting its result. This article starts to explain the mechanics of writing your own routines, by explaining the register architecture of ARM64 processors. In that first article, I glibly produced a C wrapper of extern double multadd(double, double, double) to call an assembly language routine of _multadd: STR LR, [SP, #-16]! FMADD D0, D0, D1, D2 LDR LR, [SP], #16 RET Stepping through the lines of assembly, that first saves a set of registers, performs the floating point operation I want, restores the registers, and returns. For any of that to make sense, you first need to understand the register architecture of the ARM64 processor. The processor has three main types of register: general-purpose, floating point (including SIMD) and special. When calling and running routines like this, you're most concerned with the first two, which are explained in detail in ARM's Procedure Call Standard (references below), and Apple's platform-specific document (references). armregisterarch (Tear-out PDF version: armregisterarch) There are 31 general-purpose registers, each of which can be used for 64- or 32-bit values. When used for 64-bit, they're named X0 to X30, and for 32-bit they're W0 to W30. There are 32 floating point registers, each of which can be used for 128-bit values as V0 to V31, 64-bit as D0 to D31, and 32-bit as S0 to S31. For the sake of simplicity, in this series I'll default to using 64-bit values for integers and floating point wherever possible. This means that the registers I'm going to work with most commonly are the X and D series, as in the example above. In higher language equivalents, they equate to data of types C long, pointer, Swift Int, C double and Swift Double. The first eight registers in each of these two types, X0-X7 and D0-D7, are used to pass arguments to assembly functions, and the first, X0 and D0, are used to return the result of an assembly routine. They are used in order: the first non-floating point argument will be passed in X0, the second in X1, and so on; the first floating point argument will be passed in D0, the second in D1, and so on. It's important to remember that these are used according to the register group. For a C wrapper of extern double burble(long, double, long, double) the first long will be passed in X0, the first double in D0, the second long in X1, and the second double in D1, with the result being returned in D0, as it's a double. This is the simplest way of passing arguments to an assembly routine, in which the value is used, and is placed in the register ready for the routine to access: 'call by value' (or 'pass by value'). The only result returned, in either X0 or D0, is a single value too. Passing arrays, structures and other arguments which can't simply be put into a single register requires a different method, in which a pointer to the data is passed: 'call by reference'. This is also used to enable a routine to return more than one result: when an argument is passed as a pointer to a floating point number, for example, if the routine changes the value referenced by that pointer, then that changed value is available to the code which calls that routine. Let's suppose that a floating point routine takes three doubles representing x, y and z co-ordinates, and I want it to return three changed doubles representing those co-ordinates transformed into a projected space. As only one floating point number can be returned as a result, in register D0, what we could do instead is pass those co-ordinates by reference, extern void transform(*double, *double, *double) In Swift, we might call that in turn as transform(&x, &y, &z) to pass the addresses of those Doubles. In an assembly routine, calling by value is simplest, as the values are available direct from the designated registers. Calling by reference is a bit more complicated, though, as before the routine can access values it first has to load them from the address passed. And that's where my next article starts. References Code in Assembly for Apple Silicon with the AsmAttic app (previous article on this blog) Procedure Call Standard for the Arm 64-bit Architecture (ARM) from Github Writing ARM64 Code for Apple Platforms (Apple) Stephen Smith (2020) Programming with 64-Bit ARM Assembly Language, Apress, ISBN 978 1 4842 5880 4. Daniel Kusswurm (2020) Modern Arm Assembly Language Programming, Apress, ISBN 978 1 4842 6266 5. ARM64 Instruction Set Reference (ARM). Share this: * Twitter * Facebook * Reddit * Pinterest * Email * Print * Like this: Like Loading... Related Posted in Macs, Technology and tagged Apple silicon, ARM, assembler, assembly language, M1, Xcode. Bookmark the permalink. iThere are no comments Add yours Leave a Reply Cancel reply Enter your comment here... [ ] Fill in your details below or click an icon to log in: * * * * Gravatar Email (required) (Address never made public) [ ] Name (required) [ ] Website [ ] WordPress.com Logo You are commenting using your WordPress.com account. ( Log Out / Change ) Google photo You are commenting using your Google account. ( Log Out / Change ) Twitter picture You are commenting using your Twitter account. ( Log Out / Change ) Facebook photo You are commenting using your Facebook account. ( Log Out / Change ) Cancel Connecting to %s [ ] Notify me of new comments via email. [ ] Notify me of new posts via email. [Post Comment] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] This site uses Akismet to reduce spam. Learn how your comment data is processed. Quick Links * Downloads * Mac Troubleshooting Summary * M1 Macs * Mac problem-solving * Painting topics * Painting * Long Reads Search Search for: [ ] [Search] Monthly archives * June 2021 (38) * May 2021 (80) * April 2021 (79) * March 2021 (77) * February 2021 (75) * January 2021 (75) * December 2020 (77) * November 2020 (84) * October 2020 (81) * September 2020 (79) * August 2020 (103) * July 2020 (81) * June 2020 (78) * May 2020 (78) * April 2020 (81) * March 2020 (86) * February 2020 (77) * January 2020 (86) * December 2019 (82) * November 2019 (74) * October 2019 (89) * September 2019 (80) * August 2019 (91) * July 2019 (95) * June 2019 (88) * May 2019 (91) * April 2019 (79) * March 2019 (78) * February 2019 (71) * January 2019 (69) * December 2018 (79) * November 2018 (71) * October 2018 (78) * September 2018 (76) * August 2018 (78) * July 2018 (76) * June 2018 (77) * May 2018 (71) * April 2018 (67) * March 2018 (73) * February 2018 (67) * January 2018 (83) * December 2017 (94) * November 2017 (73) * October 2017 (86) * September 2017 (92) * August 2017 (69) * July 2017 (81) * June 2017 (76) * May 2017 (90) * April 2017 (76) * March 2017 (79) * February 2017 (65) * January 2017 (76) * December 2016 (75) * November 2016 (68) * October 2016 (76) * September 2016 (78) * August 2016 (70) * July 2016 (74) * June 2016 (66) * May 2016 (71) * April 2016 (67) * March 2016 (71) * February 2016 (68) * January 2016 (90) * December 2015 (96) * November 2015 (103) * October 2015 (119) * September 2015 (115) * August 2015 (117) * July 2015 (117) * June 2015 (105) * May 2015 (111) * April 2015 (119) * March 2015 (69) * February 2015 (54) * January 2015 (39) Tags Adobe APFS Apple AppleScript Apple silicon App Store backup Big Sur Blake bug bugs Catalina Consolation Console diagnosis Disk Utility Dore El Capitan extended attributes Finder firmware Gatekeeper Gerome HFS+ High Sierra history history of painting iCloud Impressionism iOS landscape LockRattler log logs M1 Mac Mac history macOS macOS 10.12 macOS 10.13 macOS 10.14 macOS 10.15 macOS 11 malware Metamorphoses Mojave Monet Moreau MRT myth narrative naturalism OS X Ovid painting Pissarro Poussin privacy realism riddle Rubens Sargent scripting security Sierra Swift symbolism Time Machine Turner update upgrade vulnerability xattr Xcode XProtect Statistics * 8,979,786 hits Blog at WordPress.com. Footer navigation * About & Contact * Macs * Painting * Language * Tech * Life * General * Downloads * Mac problem-solving * Extended attributes (xattrs) * Painting topics * Hieronymus Bosch * English language * LockRattler: 10.12 Sierra * LockRattler: 10.13 High Sierra * LockRattler: 10.11 El Capitan * Updates: El Capitan * Updates: Sierra, High Sierra, Mojave, Catalina, Big Sur * LockRattler: 10.14 Mojave * SilentKnight, silnite, LockRattler, SystHist & Scrub * DelightEd & Podofyllin * xattred, Metamer, Sandstrip & xattr tools * 32-bitCheck & ArchiChect * T2M2, Ulbow, Consolation and log utilities * Cirrus & Bailiff * Taccy, Signet, Precize, Alifix, UTIutility, Sparsity, alisma * Revisionist & DeepTools * Text Utilities: Nalaprop, Dystextia and others * PDF * Keychains & Permissions * LockRattler: 10.15 Catalina * Updates * Spundle, Cormorant, Stibium, Dintch, Fintch and cintch * Long Reads * LockRattler: 11.0 Big Sur * Mac Troubleshooting Summary * M1 Macs * Mints: a multifunction utility Secondary navigation * Search Post navigation Painting Within Tent: Audubon's birds 1 Painting Within Tent: Audubon's birds 2 Search for: [ ] [Search] Begin typing your search above and press return to search. Press Esc to cancel. Write a Comment... [ ] Email (Required) [ ] Name (Required) [ ] Website [ ] [Post Comment] Loading Comments... Comment x Send to Email Address [ ] Your Name [ ] Your Email Address [ ] [ ] loading [Send Email] Cancel Post was not sent - check your email addresses! Email check failed, please try again Sorry, your blog cannot share posts by email. %d bloggers like this: [b]