Assembly 指向函数的程序集传递指针
我试图将DWORD变量作为指针参数发送到函数中Assembly 指向函数的程序集传递指针,assembly,x86,libc,calling-convention,fasm,Assembly,X86,Libc,Calling Convention,Fasm,我试图将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
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,为什么?您要确保完成后弹出vars 看看你的例子,我发现变量不可能是11。在
dd
作业中,它从1开始,如果你在lea中的数学是正确的,那么它将是10。如果要通过调试器逐步执行此操作,可以检查lea/mov
组合是否正常工作。无论哪种情况,我都会期望1或10,而不是11
也许你想添加
而不是mov
您是否确保完成后弹出VAR
看看你的例子,我发现变量不可能是11。在dd
作业中,它从1开始,如果你在lea中的数学是正确的,那么它将是10。如果要通过调试器逐步执行此操作,可以检查lea/mov
组合是否正常工作。无论哪种情况,我都会期望1或10,而不是11
也许你想添加而不是mov
主要问题是,当您执行推送[variable1]
时,您没有将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
跑步时,您应获得:
十一,
等效的C代码如下所示:
#include <stdio.h>
void _InitPointer (int *ptr)
{
*ptr += 10;
return;
}
int variable1 = 1;
int main()
{
_InitPointer (&variable1);
printf ("%d\n", variable1);
return 0;
}
主要问题是,在执行推送[variable1]
操作时,没有将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
跑步时,您应获得:
十一,
等效的C代码如下所示:
#include <stdio.h>
void _InitPointer (int *ptr)
{
*ptr += 10;
return;
}
int variable1 = 1;
int main()
{
_InitPointer (&variable1);
printf ("%d\n", variable1);
return 0;
}
确保完成后你能打开你的Var是吗?看看你的例子,我发现变量不可能是11。在dd
作业中,它从1开始,如果lea
中的数学正确,那么它将是10。如果要通过调试器逐步执行此操作,可以检查lea/mov
组合是否正常工作。无论哪种情况,我都会期望1或10,而不是11。也许你是想add
而不是`mov
?在调用后,我添加了pop[variable1],它可以工作。很抱歉,我是想添加而不是mov。只是为了完整性:你假设了被调用方堆栈清理约定,但实现了调用方堆栈清理约定。通过清理堆栈,您可以自己有效地解决此问题。看看你为什么自己解决了问题。为什么我可以“推他之后不弹出数组”?按my_数组调用my_func;按我的数组调用我的函数,确保完成后弹出变量是吗?看看你的例子,我发现变量不可能是11。在dd
作业中,它从1开始,如果lea
中的数学正确,那么它将是10。如果要通过调试器逐步执行此操作,可以检查lea/mov
组合是否正常工作。无论哪种情况,我都会期望1或10,而不是11。也许你是想add
而不是`mov
?在调用后,我添加了pop[variable1],它可以工作。很抱歉,我是想添加而不是mov。只是为了完整性:你假设了被调用方堆栈清理约定,但实现了调用方堆栈清理约定。通过清理堆栈,您可以自己有效地解决此问题。看看你为什么自己解决了问题。为什么我可以“推他之后不弹出数组”?按my_数组调用my_func;push my_array call my_funcI在Windows上。您说过“LEA没有获取存储在堆栈上的地址,而是获取应该存储地址的堆栈位置的地址。”因此,如果push[variable]
没有发送变量的地址,那么它是如何正常工作的?我猜leaeax,dword[ebp+8]
正在加载堆栈地址,变量的值在哪里,然后mov dword[eax],10'正在将10加载到堆栈地址,该值在哪里,但原始的变量'是如何变化的?因为当我们按值发送参数时,复制(从C)@Alatristepush[variable1]
的编译器按值推送variable1
。将值1放在堆栈顶部(不是variable1的地址)leaeax,dword[ebp+8]
将值1存储在堆栈上的地址(不是variable1
的实际位置)移动到eax中。然后使用add
修改堆栈上的值。返回pop[variable1]
后,从堆栈顶部取出修改后的值,并将其存储(复制)到variable1
的内存地址。虽然这是可行的,但事实并非如此