Assembly pass pointer to function

五迷三道 提交于 2019-12-02 02:18:55

问题


I'm trying to sent DWORD variable into function as pointer paramater

variable1 dd 1
...
push [variable1]  ; push variable adress
call _InitPoiner
...
_InitPoiner:
    ;
    push ebp
    mov ebp, esp
    ;
    lea eax, [ebp+8]       ; load address
    mov dword [eax], 10    ; move value 10 into that address

    pop ebp
    ret
...
push [variable1]
push sdigit ; where sdigit db '%d', 0x0D, 0x0A, 0
call [printf]

but variable1 is 1, not 11 , why?


回答1:


You are making sure that you pop your vars when done?

Looking at your example, I see no way that the variable could ever be 11. It starts as 1 at the dd assignment, then if your math in the lea is correct, it would then be 10. If you were to step this through a debugger, you could check if your lea / mov combo is working right. Either way, I would expect 1 or 10, not 11.

Maybe you meant to add instead of mov?




回答2:


The main problem is that you are not pushing the address of variable1 onto the stack when you do push [variable1]. That pushes the 32-bit value stored at variable1 which happens to be the value of 1. To push the address you would use push variable1 without the brackets.

When pushing values onto the stack before a call you need to restore the stack after the call.

LEA wasn't getting the address stored on the stack but getting the address of the stack location where the address should have been stored. I think you were looking for something like:

format ELF

extrn printf
public main

section '.text' executable
main:
    push variable1         ; push address of variable
    call _InitPointer
    add esp, 4             ; We pushed 4 bytes before calling function
                           ; restore the stack by adding 4

    push [variable1]       ; Push the value at address variable1
    push sdigit            ; Format specifier for printf
    call printf
    add esp, 8             ; We pushed 8 bytes of data for call
                           ; restore the stack by adding 8
    ret

_InitPointer:
    push ebp
    mov ebp, esp

    mov eax, [ebp+8]       ; There is an address at [ebp+8] that
                           ; was pushed as the 1st parameter. Put the
                           ; address in EAX

    add dword [eax], 10    ; Add the value 10 to the DWORD value that is at
                           ; address in EAX

    pop ebp
    ret

section '.data' writeable
variable1 dd 1
sdigit db '%d', 0x0D, 0x0A, 0

You didn't mention the platform you are on as you didn't supply a minimal complete verifiable example. The code above could be tested on Linux with:

fasm test.asm
gcc -o test -m32 test.o

When run you should get:

11

The equivalent C code would look like:

#include <stdio.h>

void _InitPointer (int *ptr)
{
    *ptr += 10;
    return;
}

int variable1 = 1;

int main()
{
    _InitPointer (&variable1);
    printf ("%d\n", variable1);
    return 0;
}

Note: If on modern versions of Linux, 32-bit programs follow System V i386 ABI that requires the stack be 16-byte (or 32-byte) aligned at the point of a function call. I didn't do that in the code above to keep it simplified but it should be taken into account. I'm unsure if you are on Linux or Windows. Your question doesn't say.


32-bit Windows Version

format PE console 4.0
include 'win32a.inc'

main:
    push variable1         ; push address of variable
    call _InitPointer
    add esp, 4             ; We pushed 4 bytes before calling function
                           ; restore the stack by adding 4

    push [variable1]       ; Push the value at address variable1
    push sdigit            ; Format specifier for printf
    call [printf]
    add esp, 8             ; We pushed 8 bytes of data for call
                           ; restore the stack by adding 8
    push 0                 ; Exit with return value 0
    call [ExitProcess]

_InitPointer:
    push ebp
    mov ebp, esp

    mov eax, [ebp+8]       ; There is an address at [ebp+8] that
                           ; was pushed as the 1st parameter. Put the
                           ; address in EAX

    add dword [eax], 10    ; Add the value 10 to the DWORD value that is at
                           ; address in EAX

    pop ebp
    ret

variable1 dd 1
sdigit db '%d', 0x0D, 0x0A, 0

data import
 library kernel32,'KERNEL32.DLL',\
         msvcrt,'MSVCRT.DLL'
 import msvcrt,\
        printf ,'printf'
 import kernel32,\
        ExitProcess,'ExitProcess'
end data


来源:https://stackoverflow.com/questions/42820117/assembly-pass-pointer-to-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!