旅游酒店网站建设,设计制作费用计入什么会计科目,wordpress判断页面,咖啡网站建设的优势X86_64函数调用汇编程序分#xff08;2#xff09; 1 X86_64寄存器使用标准2 leaveq和retq指令2.1 leaveq2.2 retq 3 执行leaveq和retq之后栈的结构3.1 执行leaveq之后栈的结构3.1.1 test_fun_b函数执行leaveq之前的栈结构示意图3.1.2 test_fun_b函数执行leaveq之后的栈结构示… X86_64函数调用汇编程序分2 1 X86_64寄存器使用标准2 leaveq和retq指令2.1 leaveq2.2 retq 3 执行leaveq和retq之后栈的结构3.1 执行leaveq之后栈的结构3.1.1 test_fun_b函数执行leaveq之前的栈结构示意图3.1.2 test_fun_b函数执行leaveq之后的栈结构示意图 3.2 执行retq之后栈的结构3.2.1 test_fun_b函数执行retq之前的栈结构示意图3.2.2 test_fun_b函数执行retq之后的栈结构示意图 X86_64函数调用汇编程序分析
1 X86_64寄存器使用标准
%rdi, %rsi, %rdx, %rcx, %r8, %r9分别用于函数调用过程中的前6个参数对于6的参数存放在栈中传递%rsp用做栈指针寄存器指向栈顶%rbp用作栈框寄存器指向栈底%rax用做函数返回值的第一个寄存器%rip寄存器可以当做PC寄存器程序计数器使用。它用于存储下一条要执行的指令的地址。[ In 64-bit mode, the RIP register becomes the instruction pointer. This register holds the 64-bit offset of the next instruction to be executed. 64-bit mode also supports a technique called RIP-relative addressing. Using this technique, the effective address is determined by adding a displacement to the RIP of the next instruction.(在 64 位模式下RIP 寄存器成为指令指针。该寄存器保存下一条要执行指令的 64 位偏移量。64 位模式还支持一种称为 RIP 相对寻址的技术。使用这种技术有效地址是通过在下一条指令的 RIP 中加入一个位移来确定的。) ]
2 leaveq和retq指令
2.1 leaveq
x86_64架构的leaveq指令是一个伪指令它并不是一条单独的指令而是由两条实际指令组合而成的。具体来说leaveq的功能等效于pop %rbp; mov %rbp, %rsp这两条指令。
首先让我们来了解一下这两条指令的含义
mov %rbp, %rsp这条指令将栈指针寄存器%rbp的值复制到基指针寄存器%rsp中。在x86_64架构中%rsp寄存器用于保存当前线程的栈指针指向栈顶位置。而%rbp寄存器通常用作基指针指向函数调用堆栈的底部。 pop %rbp这条指令弹出栈顶的值并将其存储在%rbp寄存器中。在函数调用过程中%rbp寄存器的值通常被保存起来用于在函数返回时恢复函数调用堆栈的状态。 那么为什么需要这两条指令的组合呢在x86_64架构中当函数调用发生时处理器会将函数的参数和局部变量压入栈中同时保存一些寄存器的值如%rbp以供函数内部使用。当函数执行完毕并准备返回时需要恢复这些寄存器的值并清理栈中的局部变量。这就是leaveq伪指令的作用。
通过执行mov %rbp, %rsp和pop %rbp这两条指令可以将栈指针的值复制到%rbp寄存器中并弹出栈顶的值恢复%rbp寄存器的原始值。这样函数返回后栈指针和基指针的值都得到了恢复保证了程序的正确执行。
需要注意的是leaveq伪指令的执行并不会改变任何寄存器的值只会影响栈指针和基指针的状态。因此它通常用于函数返回之前的准备阶段以确保正确的控制流和栈状态。
总结一下x86_64架构的leaveq伪指令是一个用于恢复函数调用堆栈状态的指令组合它等效于mov %rbp, %rsp; pop %rbp这两条实际指令的功能。在执行leaveq后栈指针和基指针的值会得到恢复为函数返回做好准备。
2.2 retq
x86_64架构中的retq指令是用于从当前函数调用中返回的指令。在函数调用完成后retq指令会将控制权返回给调用者同时恢复堆栈状态和寄存器的值。
首先让我们来了解一下retq指令的作用。当函数执行到retq指令时处理器会从当前函数调用的堆栈中弹出返回地址并将控制流转移到该地址处。这个地址通常是在函数调用时被压入栈中的。因此在函数返回时控制权会返回到调用该函数的地方。
在执行retq指令时处理器还会恢复一些寄存器的值。例如在函数调用发生时基指针寄存器%rbp的值通常会被保存起来用于在函数返回时恢复堆栈的状态。同样地栈指针寄存器%rsp的值也可能会被保存和恢复。这些操作是隐式的不需要程序员显式地编写指令来完成。
另外关于retq指令的执行时机它通常出现在函数的末尾即当函数的所有操作都完成后才会执行。在某些情况下如果函数使用了递归或者其他更复杂的控制流程可能会在更早的时候使用retq指令来提前返回。但是在函数执行完毕之前使用retq指令是不允许的否则会导致程序崩溃或其他错误。
需要注意的是如果使用汇编语言来编写程序通常需要根据具体的架构和编译器来编写代码。虽然x86_64架构中的retq指令可以用来实现函数返回的操作但是使用汇编语言编写程序需要考虑到很多细节和注意事项包括对寄存器的使用、内存访问以及其他底层操作的处理。因此除非必要否则建议尽可能使用高级语言来编写程序以避免出现一些难以预料的问题。
总之x86_64架构中的retq指令是用于从当前函数调用中返回的指令。它通过弹出堆栈中的返回地址并将控制流转移到该地址来实现函数返回的操作。同时一些寄存器的值也会得到恢复以确保程序在返回之前处于正确的状态。
3 执行leaveq和retq之后栈的结构
3.1 执行leaveq之后栈的结构
3.1.1 test_fun_b函数执行leaveq之前的栈结构示意图 3.1.2 test_fun_b函数执行leaveq之后的栈结构示意图
在test_fun_b调用leaveq之后test_fun_b的栈空间就会被释放掉该指令执行的操作为
pop %rbp
mov %rbp, %rsp;3.2 执行retq之后栈的结构
通常情况下leaveq和retq是依次被调用到的。leaveq是为了恢复%rsp寄存器的值而ret会把返回地址从栈中弹出并将%rip指向弹出的返回地址。
3.2.1 test_fun_b函数执行retq之前的栈结构示意图 3.2.2 test_fun_b函数执行retq之后的栈结构示意图
retq会把返回地址从栈从弹出并更新%rip寄存器的值为返回地址的值同时也会更新%rsp寄存器的值。