While reading and learning from open source OSes I stumbled across an extremely complicated way of calling a "method" in assembly. It uses the 'ret' instruction to call a library method doing this:
push rbp ; rsp[1] = rbp
mov rbp, .continue ; save return label to rbp
xchg rbp, QWORD [rsp] ; restore rbp and set rsp[1] to return label
push rbp ; rsp[0] = rbp
mov rbp, 0x0000700000000000 + LIB_PTR_TABLE.funcOffset ; rbp = pointer to func pointer
mov rbp, QWORD [rbp] ; rbp = func pointer
xchg rbp, QWORD [rsp] ; restore rbp and set rsp[0] to func pointer
; "call" library by "returning" to the address we just planted
ret
.continue:
I added the comments in order to understand it myself and it seems I am right or close enough because all experiments I did succeeded. But then i tried doing this, which also works perfectly:
mov rax, 0x0000700000000000 + LIB_PTR_TABLE.funcOffset ; rax = ptr to func ptr
mov rax, QWORD [rax] ; rax = func ptr
call rax ; actually call the library function in a normal fashion
Looking at the amount of instructions and what the CPU actually has to do in both cases one would assume, if one was faster it would be the "call" variant. But since the "ret" variant was used and coming up with this requires a bunch of knowledge in the first place, what advantages does the first variant have? (Or does it?)