这种交换在推送寄存器方面有多安全?

时间:2016-02-14 21:01:51

标签: c visual-studio assembly x86 masm

我对Assembly非常新,下面的代码应该通过两个不同的函数交换两个整数:首先使用swap_c然后使用swap_asm

但是,我怀疑,我是否需要在汇编代码之前push(我的意思是保存)寄存器的每个值,以及稍后pop它们(在返回main之前)。换句话说,如果我返回不同的寄存器内容(不是像ebpesp这样的关键内容,CPU会不会生我的气;但是,只有eaxebx,运行ecx功能后edx& swap_asm)?取消注释装配部件中的线条会更好吗?

这段代码对我来说运行正常,我设法将27行汇编的C代码减少到7条装配线。

p.s。:系统是Windows 10,VS-2013 Express。

main.c部分

#include <stdio.h>

extern void swap_asm(int *x, int *y);

void swap_c(int *a, int *b) {
    int t = *a;
    *a = *b;
    *b = t;
}

int main(int argc, char *argv[]) {
    int x = 3, y = 5;
    printf("before swap    => x = %d     y = %d\n\n", x, y);

    swap_c(&x, &y);
    printf("after swap_c   => x = %d     y = %d\n\n", x, y);

    swap_asm(&x, &y);
    printf("after swap_asm => x = %d     y = %d\n\n", x, y);

    getchar();
    return (0);
}

assembly.asm部分

 .686
.model flat, c
.stack 100h
.data

.code
swap_asm proc
    ; push eax
    ; push ebx
    ; push ecx
    ; push edx
    mov eax, [esp] + 4  ; get address of "x" stored in stack into eax
    mov ebx, [esp] + 8  ; get address of "y" stored in stack into ebx
    mov ecx, [eax]      ; get value of "x" from address stored in [eax] into ecx
    mov edx, [ebx]      ; get value of "y" from address stored in [ebx] into edx
    mov [eax], edx      ; store value in edx into address stored in [eax]
    mov [ebx], ecx      ; store value in ecx into address stored in [ebx]
    ; pop edx
    ; pop ecx
    ; pop ebx
    ; pop eax
    ret
swap_asm endp
end

1 个答案:

答案 0 :(得分:8)

通常,这取决于您正在使用的系统的调用约定。 调用约定指定如何调用函数。通常,它会说明放置参数的位置以及被调用函数必须保留哪些寄存器。

在具有cdecl调用约定的i386 Windows上(您可能使用的那个),您可以自由覆盖eaxecxedx寄存器。必须保留ebx寄存器。虽然您的代码似乎有效,但当函数开始依赖于ebx被保留时,它会神秘地失败,因此最好保存并恢复它。