ASM x86函数调用:保存EBP和公共寄存器的最佳方法(EAX,EBX,...)

时间:2014-05-18 21:28:04

标签: assembly x86

我想知道除了EBP之外,保存公共寄存器(EAX,EBX等)的最佳方法是什么。 这是我的示例代码。它juste调用我的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的保存。我看到了三种保存公共寄存器的方法:

  • 首先,在“mov%esp,%ebp”之前(在为ebp分配新地址之前)将它们保存在写入功能中。 =>问题:ESP,因此EBP将在公共寄存器值之后指向堆栈,因此我将不得不在堆栈中更深入地找到参数(我将不得不在之前通过EAX,EBX,ECX,EDX的值)找到参数)

  • 其次,在“mov%esp,%ebp”之后将它们保存在write函数中。 =>问题:ESP,所以EBP将在公共寄存器值之前指向堆栈,因此我将不得不在堆栈中继续使用局部变量(如果我保存EAX,EBX,我将不得不传递4个值) ECX和EDX,我的本地变量的开头地址)。

  • 第三,在函数调用之前(以及在推送参数之前)将它们保存在调用函数(这里是main)中。没有堆栈的问题,但我觉得这不是很优雅,我需要为每个呼叫添加8行(在通话前4次按下,4次弹出后)。

那么,什么是最好的方法?当然是另一种我没想到的方法:)

感谢您的帮助!

2 个答案:

答案 0 :(得分:2)

如果您决定使用帧指针,通常要做的是在设置ebp后保存它们。您保存的寄存器与任何本地变量没有区别,如果您愿意,您甚至可以使用mov指令而不是push / pop来访问它们,如果您愿意,可以将它们置于其他变量之下不想使用更大的抵消。

请注意,通常不需要帧指针,因为您可以相对于esp进行寻址。此外,常见的通话约定通常允许修改eaxecxedx,因此如果您坚持这一点,则需要保存ebx

答案 1 :(得分:0)

如果您不确定寄存器'情况,这些说明可以轻松地节省一天。

PUSHA/PUSHAD -- Push all General Registers
POPA/POPAD -- Pop all General Registers

这些指令按一定顺序推送和弹出通用和SI / ESI,DI / EDI寄存器。

PUSHA / PUSHAD指令的顺序如下。

Opcode  Instruction  Clocks   Description

60      PUSHA        18       Push AX, CX, DX, BX, original SP, BP, SI, and DI
60      PUSHAD       18       Push EAX, ECX, EDX, EBX, original ESP, EBP ESI, and EDI

POPA / POPAD指令的顺序如下。 (按相反顺序)

Opcode   Instruction   Clocks   Description

61       POPA          24       Pop DI, SI, BP, SP, BX, DX, CX, and AX
61       POPAD         24       Pop EDI, ESI, EBP, ESP(***),EBX, EDX, ECX, and EAX

*** ESP值被丢弃而不是加载到ESP中。