tags:

views:

1097

answers:

3

Let's say we have the following c++ code:

int var1;

__asm {
    mov var1, 2;
}

Now, what I'd like to know is if I didn't want to define var1 outside the __asm directive, what would I have to do to put it inside it. Is it even possible?

Thanks

+1  A: 

It' impossible to create a C variable in assembler: the C compiler has to know about the variable (ie its type and address), which means it has to be declared in the C code.

What can be done is accessing symbols defined in assembler via extern declarations in C. That won't work for variables with automatic storage duration, though, as these don't have a fixed address but are referenced relative to the base pointer.

If you don't want to access the variables outside of the asm block, you can use the stack for storing assembler-local data. Just keep in mind that you have to restore the stack pointer to its previous value when leaving the asm block, eg

sub esp, 12       ; space for 3 asm-local 32bit vars
mov [esp-8], 42   ; set value of local var
[...]
push 0xdeadbeaf   ; use stack
[...]             ; !!! 42 resides now in [esp-12] !!!
add esp, 16       ; restore esp

If you don't want the relative addresses of the local variables to change whenever you manipulate the stack (ie use push or pop), you have to establish a stack frame (ie save the base of the stack in ebp and address locals relative to this value) as described in cedrou's answer.

Christoph
Are you sure sub esp, 3 will give space for 3 32bit vars? I had the idea that for each 32bit var i'd have to take 4 from esp.
devoured elysium
At least c++ defines internally it like this: var_4= dword ptr -4
devoured elysium
you're right - shouldn't answer questions this late at night ;)
Christoph
+8  A: 

To do that, you'll need to create a "naked" method with _declspec(naked) and to write yourself the prolog and the epilog that are normally created by the compiler.

The aim of a prolog is to:

  • set up EBP and ESP
  • reserve space on stack for local variables
  • save registers that should be modified in the body of the function

An epilog has to:

  • restore the saved register values
  • clean up the reserved space for local variables

Here is a standard prolog

push        ebp                ; Save ebp
mov         ebp, esp           ; Set stack frame pointer
sub         esp, localbytes    ; Allocate space for locals
push        <registers>        ; Save registers

and a standard epilog:

pop         <registers>   ; Restore registers
mov         esp, ebp      ; Restore stack pointer
pop         ebp           ; Restore ebp
ret                       ; Return from function

Your local variables will then begin at (ebp - 4) and go downward to (ebp - 4 - localbytes). The function parameters will start at (ebp + 8) and go upward.

cedrou
+3  A: 

Local variables are allocated and freed by manipulating the available space on the call stack via the ESP register, ie:

__asm
{
    add esp, 4
    mov [esp], 2;
    ...
    sub esp, 4
}

Generally, this is better handled by establishing a "stack frame" for the calling function instead, and then access local variables (and function parameters) using offsets within the frame, instead of using the ESP register directly, ie:

__asm
{
    push ebp
    mov ebp, esp
    add esp, 4
    ...
    mov [ebp-4], 2;
    ...
    mov esp, ebp
    pop ebp
}
Remy Lebeau - TeamB