Assembly 更改地址在堆栈中的变量

Assembly 更改地址在堆栈中的变量,assembly,x86,masm,irvine32,Assembly,X86,Masm,Irvine32,假设这是我的主要任务 main PROC sub esp, 4 push OFFSET variableName call changeVariable changeVariable PROC push ebp mov ebp, esp 如何在changeVariable过程中将variableName更改为不同的值(例如,10) 我试过了 mov OFFSET[ebp+8], 10 ;ebp[+8] is the position in stack

假设这是我的主要任务

main PROC
    sub esp, 4
    push OFFSET variableName
    call changeVariable

changeVariable PROC
    push ebp
    mov ebp, esp
如何在changeVariable过程中将variableName更改为不同的值(例如,10)

我试过了

mov OFFSET[ebp+8], 10  ;ebp[+8] is the position in stack that holds address of variableName
但这对你的尝试不起作用

mov OFFSET[ebp+8], 10
间接或索引操作数对于
OFFSET
运算符无效,我认为您误解了
OFFSET
的返回值,它是一个立即操作数,“数据的有效地址”,另外,
OFFSET
运算符的返回值会使
MOV
指令的目标操作数成为无效的立即操作数

在您的情况下,如果堆栈上已存在
variableName
的偏移量,请首先在临时寄存器中加载该偏移量,并仅使用间接操作数解引用,但必须使用
PTR
运算符指定大小

mov esi,[ebp+8]
mov DWORD PTR[esi],10
关于你的尝试

mov OFFSET[ebp+8], 10
间接或索引操作数对于
OFFSET
运算符无效,我认为您误解了
OFFSET
的返回值,它是一个立即操作数,“数据的有效地址”,另外,
OFFSET
运算符的返回值会使
MOV
指令的目标操作数成为无效的立即操作数

在您的情况下,如果堆栈上已存在
variableName
的偏移量,请首先在临时寄存器中加载该偏移量,并仅使用间接操作数解引用,但必须使用
PTR
运算符指定大小

mov esi,[ebp+8]
mov DWORD PTR[esi],10

您正在按指针,如注释中所述,您需要遵守它。
请参阅此C代码所在的位置

void bar(int* c)
{
    *c = 10;
}

void foo(int c)
{
        c = 10;
}

int myVar;

int main()
{
    bar(&myVar);

    foo(myVar);
}
组装成

bar:
        push    ebp
        mov     ebp, esp

        ;What you need to do:
        mov     eax, DWORD PTR [ebp+8]     ;Read the pointer
        mov     DWORD PTR [eax], 10        ;Deference it

        nop
        pop     ebp
        ret

foo:
        push    ebp
        mov     ebp, esp

        ;What you are doing:
        mov     DWORD PTR [ebp+8], 10  ;Overwriting an argument

        nop
        pop     ebp
        ret

main:
        push    ebp
        mov     ebp, esp

        ;This is you call exactly
        push    OFFSET FLAT:myVar
        call    bar
        add     esp, 4

        ;How one would call the foo version
        mov     eax, DWORD PTR myVar
        push    eax
        call    foo
        add     esp, 4


        mov     eax, 0
        leave
        ret
特别注意C代码
foo
bar
对应的内容。

这可能有助于您理解差异

您正在按一个指针,正如您需要遵守的注释中所述。
请参阅此C代码所在的位置

void bar(int* c)
{
    *c = 10;
}

void foo(int c)
{
        c = 10;
}

int myVar;

int main()
{
    bar(&myVar);

    foo(myVar);
}
组装成

bar:
        push    ebp
        mov     ebp, esp

        ;What you need to do:
        mov     eax, DWORD PTR [ebp+8]     ;Read the pointer
        mov     DWORD PTR [eax], 10        ;Deference it

        nop
        pop     ebp
        ret

foo:
        push    ebp
        mov     ebp, esp

        ;What you are doing:
        mov     DWORD PTR [ebp+8], 10  ;Overwriting an argument

        nop
        pop     ebp
        ret

main:
        push    ebp
        mov     ebp, esp

        ;This is you call exactly
        push    OFFSET FLAT:myVar
        call    bar
        add     esp, 4

        ;How one would call the foo version
        mov     eax, DWORD PTR myVar
        push    eax
        call    foo
        add     esp, 4


        mov     eax, 0
        leave
        ret
特别注意C代码
foo
bar
对应的内容。

这可能有助于您理解差异

你需要再次取消引用。将地址加载到暂存寄存器中,然后取消引用。您需要另一次取消引用。将地址加载到一个临时寄存器中,然后删除它。哈哈!没问题。我以前遇到过“Ooops我一直在测试错误的程序”的情况;-)。我现在就删除我以前的评论哈哈!没问题。我以前遇到过“Ooops我一直在测试错误的程序”的情况;-)。我现在将删除我以前的评论