Page 147 - ARM 64 Bit Assembly Language
P. 147

Structured programming 133

                     the type indicated in the conversion specifier. The first conversion specifier is applied to the
                     second argument, the second conversion specifier is applied to the third argument, the third
                     conversion specifier is applied to the fourth argument, and so on. The %d conversion specifiers
                     indicate that the arguments are to be interpreted as integers and printed in base ten.

                     Listing 5.26 shows an equivalent call made in AArch64 assembly language. Since there are
                     eleven arguments, the last three must be pushed to the program stack. The arguments are
                     loaded into w9-w11 and then the arguments are stored on the stack in reverse order. Even
                     though the parameters are 4 bytes each, they are pushed onto the stack using eight bytes each.
                     The top four bytes are padding. Note that the eleventh argument is placed in the stack at a
                     higher location than the ninth and tenth arguments. Line 10 decrements the stack pointer by
                     32 bytes, providing room for up to four 8-byte double-words. This is necessary because the
                     AArch64 stack pointer must always be on a 16-byte boundary. Since we have three 8-byte ar-
                     guments to push, we must allocate 32 bytes, rounding up to the next 16-byte boundary. It then
                     stores x9 at address of the stack pointer, and x10 eight bytes above that. Line 11 stores x11 16
                     bytes above the (decremented) stack pointer. The remaining arguments are loaded in x0-x7.
                     Note that we assume that format has previously been defined to be "The results are:
                     %d %d %d %d %d\n" using an .asciz or .string assembler directive.

                     Listing 5.27 shows how the eleventh, tenth, and ninth arguments can be pushed to the stack
                     using a stp instruction and str instruction. This would be slightly more efficient than the
                     code shown in Listing 5.26. The eleventh argument is loaded into w11, the tenth argument is
                     loaded into w10, and the ninth argument is loaded into w9, then the stp instruction is used to
                     store w9 and w10 on the stack and adjust the stack pointer. After w11 is stored on the stack,
                     note that they have been placed in reverse order.

                     A little care must be taken to ensure that the arguments are stored in the correct order on the
                     stack. Remember that the stp instruction will always push the first register to the lower ad-
                     dress, and the stack grows downward. Therefore, x9, which is the ninth argument will be
                     pushed onto the stack first. Because pre-indexing is used, x9 is actually at the highest address.
                     The 64-bit notation is used because otherwise stp would store both registers in just 8 bytes,
                     and 16 bytes are needed. Additionally, the printf instruction does not care what the rest of
                     the bits are for each int, they are just treated as padding on the stack. Moreover, the x9 register
                     has zeroes in the upper 32-bits because 32-bit operations, such as ldr zero the upper bits un-
                     less they are explicitly sign-extended using an instruction like ldrsw. Finally, the stack must
                     always be 16-byte aligned, which is why it is pushed down 32 bytes instead of just 24.

                     After the printf function is called, the ninth, tenth, and eleventh arguments must be popped
                     from the stack. If those values are no longer needed, then there is no need to load them into
                     registers. The quickest way to pop them from the stack is to simply adjust the stack pointer
                     back to its original value. In this case, we pushed three arguments onto the stack, using a total
   142   143   144   145   146   147   148   149   150   151   152