【发布时间】:2014-07-06 18:45:48
【问题描述】:
我想知道除了 EBP 之外保存通用寄存器(EAX、EBX 等)的最佳方法是什么。 这是我的示例代码。它只是调用我的 write 函数,在参数中传递字符串地址和长度(参数放在堆栈中)。 在 write 函数中,我保存 EBP,给它新的值,取回参数并调用 write syscall。
.section .data
ask_number_str:
.ascii "Hello world"
anstr_end:
.set ANSTR_SIZE, anstr_end - ask_number_str
.section .bss
.section .text
.globl main
main:
movl $42, %eax
movl $123, %ebx
movl $456, %ecx
movl $789, %edx
pushl $ANSTR_SIZE
pushl $ask_number_str
call write
add $8, %esp
exit:
movl $1, %eax
movl $0, %ebx
int $0x80
write:
pushl %ebp
movl %esp, %ebp
movl $4, %eax
movl $1, %ebx
movl 8(%ebp), %ecx
movl 12(%ebp), %edx
int $0x80
popl %ebp
ret
我想在函数调用时添加 EAX、EBX、ECX 和 EDX 的保存。我看到了三种保存常用寄存器的方法:
首先,将它们保存在 write 函数中,在“mov %esp, %ebp”之前(在为 ebp 分配新地址之前)。 => 问题:ESP,所以 EBP 会在堆栈中指向公共寄存器值之后,所以我必须深入堆栈才能找到参数(我必须通过 EAX、EBX、ECX 的值,找到参数之前的EDX)
其次,将它们保存在写入函数中,在“mov %esp, %ebp”之后。 => 问题:ESP,因此 EBP 将在堆栈中指向公共寄存器值之前,所以我将不得不在堆栈中更深入地使用局部变量(如果我保存 EAX,我将必须传递 4 个值, EBX、ECX 和 EDX,以获取我的局部变量的起始地址)。
第三,将它们保存在调用函数(这里是主函数)中,在函数调用之前(以及在参数推送之前)。栈没问题,但是我觉得这不是很优雅,每次调用都需要加8行(调用前4个push,后4个pop)。
那么,对你来说最好的方法是什么?当然是另一种我没有想到的方法:)
感谢您的帮助!
【问题讨论】: