Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How safe is this swap w/o pushing registers?

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
like image 244
ssd Avatar asked Feb 14 '16 21:02

ssd


People also ask

What does it mean to push a register?

pushing a value (not necessarily stored in a register) means writing it to the stack. popping means restoring whatever is on top of the stack into a register.

What does popping a register do?

Registers are popped in order (smallest number first) so if you push a list of registers and then pop the same list, the values end up in the same locations.

Does push change value of register?

The register keeps its value after push instruction.

What does the push instruction do?

The PUSH instruction increments the stack pointer and stores the value of the specified byte operand at the internal RAM address indirectly referenced by the stack pointer. No flags are affected by this instruction.


1 Answers

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.

like image 122
fuz Avatar answered Sep 22 '22 09:09

fuz