首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >程序集指向函数的指针

程序集指向函数的指针
EN

Stack Overflow用户
提问于 2019-05-22 00:55:11
回答 2查看 0关注 0票数 0

我正在尝试将DWORD变量作为指针参数发送到函数中

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]

但是variable1是1,而不是11,为什么?

EN

回答 2

Stack Overflow用户

发布于 2019-05-22 09:29:47

你确定在完成后弹出你的变种?

看看你的例子,我认为变量不可能是11。它在dd赋值时从1开始,然后如果你在lea中的数学是正确的,那么它将是10.如果你通过调试器执行此操作,你可以检查你的lea / mov组合是否正常工作。无论哪种方式,我预计1或10,而不是11。

也许你的意思是add代替mov

票数 0
EN

Stack Overflow用户

发布于 2019-05-22 10:41:28

主要的问题是,你是不是推地址variable1压入堆栈当你这样做push [variable1]。这会推送存储在variable1的32位值,该值恰好是值1.要推送您将使用的地址push variable1而不使用括号。

在呼叫之前将值推入堆栈时,您需要在呼叫后恢复堆栈。

LEA没有获取存储在堆栈中的地址,而是获取应该存储地址的堆栈位置的地址。我想你正在寻找类似的东西:

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

您没有提到您所使用的平台,因为您没有提供最小的完整可验证示例。上面的代码可以在Linux上测试:

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

跑步时你应该得到:

11

等效的C代码如下所示:

#include <stdio.h>

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

int variable1 = 1;

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

注意:如果在现代版本的Linux上,32位程序遵循System V i386 ABI,要求堆栈在函数调用时对齐16字节(或32字节)。我没有在上面的代码中这样做,以保持简化,但应该考虑到它。我不确定你是在Linux还是Windows上。你的问题没有说。

32位Windows版本

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
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/-100006777

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档