preface

Recently I prepared to learn assembly, and then I saw the video sent by the author named iOS Xiaoxian on B website which is quite good, I plan to follow it, the article is a note to watch the video, and finally there is a link to the original video, if you want to watch the video, you can check the video through the link.

Bl and RET instructions

Bl label

  • Place the address of the next instruction into the LR (X30) register
  • Go to the label to execute the instruction

ret

  • The default value of lr(X30) register is used, and the underlying instruction prompts the CPU to use this as the next instruction address!

ARM64 platform feature instructions, it is optimized for hardware processing

X30 register

The X30 register holds the return address of the function. When the RET instruction is executed, the address value saved in the X30 register is searched!

Note: when function calls are nested. Need to push x30!

Code to rehearse

Let me write a sum function

And then I break the point at sum, and I run.

Bl jumps to sum, and once it returns, it will return to 0x102d16974 <+36>: MOV w1, #0x0, and need to save 0x102d16974 into LR (x30).

Let’s rewrite lr(x30), go to sun, then go to add sp, sp, #0x10, and type

register write lr 0x102d16934
register read lr

Copy the code

And then you keep going down

And sure enough, it’s where we rewrote it, and it doesn’t exit sum. The RET instruction is just looking for LR (x30).

Then write a compilation:

.text
.global _A,_B

_A:
    mov    x0, #0xaaaa
    bl     _B
    mov    x0, #0xbbbb
    ret


_B:
    mov    x0, #0xcccc
    ret

Copy the code

We then call A() and see that only A is printed.

Let’s try it out

0x00000001025ba948
0x1025ba950

Lr becomes 0x00000001025BA950, the address of the instruction ADRP x0, 1. Now to enter function B, lr saves the address of the next bl instruction, which is mov x0, #0xbbbb’s address 0x1025babe4, and then enters function B.

And then we keep going down and we come back to function A, lr is still 0x1025babe4, and we keep going down, and we see an infinite loop.

Let’s write two more functions C and D:

And then the break point

Instead of s, hold down the Control key and click the arrow to enter the D function

stp x29, x30, [sp, #-0x10]! This instruction is an optimized shorthand, [sp, #-0x10]! It’s sp minus 0x10 and then it’s assigned to sp, and this code is equivalent to

sub    sp,   sp,   #0x10
stp    x29,  x30,  [sp]
Copy the code

We can see that sp is now 0x000000016D7eb8e0, and then we ni, and we find that sp is indeed 0x000000016D7eb8D0 (0x000000016D7eb8e0 minus 0x10).

stp x29, x30, [sp, #-0x10]! We see that we put x29 and write x30 on the stack at the beginning of the function. LDP x29, X30, [sp], #0x10 then put the stack data into X29 and X30 before the function is called, thus protecting the X29 and X30 registers.

Perfect previous assembly code

.text
.global _A,_B

_A:
    mov    x0, #0xaaaa
    str    x30, [sp, #-0x10]!
    bl     _B
    mov    x0, #0xbbbb
    ldr    x30, [sp], #0x10
    ret


_B:
    mov    x0, #0xcccc
    ret
Copy the code

Note: We only need to save X30, not X29. Again, 0x10 can’t be 0x8, 8 bytes, and we’ve seen that stack operations are 16 bytes aligned, so 0x20, 0x30……

Run the code and print AB to show that there is no problem this time.

### Reference: BL&RET compilation (5)