不带推入寄存器的这种交换有多安全? [英] How safe is this swap w/o pushing registers?

查看:65
本文介绍了不带推入寄存器的这种交换有多安全?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

但是,我怀疑是否需要在汇编代码之前对寄存器的每个值进行 push (我的意思是保存),并在以后(即返回前)对它们进行 pop >主要).换句话说,如果我返回不同的寄存器内容(不是至关重要的内容,例如 ebp esp ;而仅仅是 eax ebx 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 []){整数x = 3,y = 5;printf(在交换之前=> x =%d y =%d \ n \ n",x,y);swap_c(& x,& y);printf("swap_c => x =%d y =%d \ n \ n",x,y);swap_asm(& x,& y);printf("swap_asm => x =%d y =%d \ n \ n",x,y);getchar();返回(0);} 

assembly.asm 零件

  .686.model平,c.堆栈100小时.数据.代码swap_asm进程;推e;推ebx;推ecx;推edxmov eax,[esp] + 4;获取存储在堆栈中的"x"的地址到eax中mov ebx,[esp] + 8;获取存储在堆栈中的"y"地址到ebx中mov ecx,[eax];从[eax]中存储的地址中获取"x"的值到ecx中mov edx,[ebx];从[ebx]中存储的地址中获取"y"的值到edx中mov [eax],edx;将edx中的值存储到[eax]中存储的地址中mov [ebx],ecx;将ecx中的值存储到[ebx]中存储的地址中;流行版;流行音乐;流行ebx;流行曲退回swap_asm endp结尾 

解决方案

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

在具有cdecl调用约定(可能是您使用的约定)的i386 Windows上,您可以自由覆盖 eax ecx edx 寄存器. ebx 寄存器必须保留.虽然您的代码看起来可以正常工作,但是当某个函数开始依赖保留 ebx 时,它神秘地失败了,因此更好地保存和恢复它.

I'm very new to Assembly and the code below is supposed to swap two integers via two different functions: first using swap_c and then using swap_asm.

However, I doubt, whether I need to push (I mean save) each value of registers before assembly code and pop them later (just before returning to main). In other words, will the CPU get mad at me if I return different register content (not the crucial ones like ebp or esp; but, just eax, ebx, ecx & edx) after running swap_asm function? Is it better to uncomment the lines in the assembly part?

This code runs OK for me and I managed to reduce the 27 lines of assembled C code down to 7 Assembly lines.

p.s.: System is Windows 10, VS-2013 Express.

main.c part

#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 part

 .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

解决方案

Generally, this depends on the calling convention of the system you are working on. The calling convention specifies how to call functions. Generally, it says where to put the arguments and what registers must be preserved by the called function.

On i386 Windows with the cdecl calling convention (which is the one you probably use), you can freely overwrite the eax, ecx, and edx registers. The ebx register must be preserved. While your code appears to work, it mysteriously fails when a function starts to depend on ebx being preserved, so better save and restore it.

这篇关于不带推入寄存器的这种交换有多安全?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆