我想构造个stdcall的函数

tjm 2001-08-04 06:09:32
加精
常听说STDCALL,不知下面的写法(函数和调用)对不对,请高手指教:
这是调用:
a dd 0
b dd 0
c dd 0
d dd 0
.........
........
push a
push b
push c
call abc
mov d,eax

;;;;;;;函数abc是这样的
BeginProc abc

Local aa:DWORD
LOCAL bb:DWORD
LOCAL cc:DWORD

mov aa,dword ptr [esp]
mov bb,dword ptr [esp+4h]
mov cc,dword ptr [esp+8h]
;;;;;;;这里是否是aa=a,bb=b,cc=c?
........
........
xor eax,eax

ret 0ch ;清栈

EndProc abc
...全文
212 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
tjm 2001-08-06
  • 打赏
  • 举报
回复
谢谢azuo_lee() 和cui(蚊子王) 
tjm 2001-08-06
  • 打赏
  • 举报
回复
我决定发分
jmt 2001-08-06
  • 打赏
  • 举报
回复
up
tjm 2001-08-05
  • 打赏
  • 举报
回复
上面的aaa,bbb是全局变量,我写错位置了。
tjm 2001-08-05
  • 打赏
  • 举报
回复
up
tjm 2001-08-04
  • 打赏
  • 举报
回复
对不起刚才有急事,下线了。
请哪位老师讲讲RET的含义。
我看了别人一段代码,完全晕了,代码结构大体如下:
Beginproc MyMain
aaa dd 0
bbb dd 0
......
mov aaa,offset32 abcd
.....
call efgh
.....
......
ret
EndProc MyMain

Beginproc efgh
pusha
.....
(没有popa)
push offset32 mnop
push aaa
ret
mnop:
......
call qrst
......
ret

abcd:
......
......
ret
qrst:
....
....
ret
Endproc efgh
现在我不清楚程序是如何执行的。
请指教。


azuo_lee 2001-08-04
  • 打赏
  • 举报
回复
呵呵,call等于push address、jmp xxx?想的有点妙,差不多。如果call是这样的话,那ret就是pop address、jmp address,呵呵……但实际运作起来可能要复杂得多,它们还是不一样的。比如有时候要压入一个偏移、一个段;或者保护模式时,根本就是调用门。
关于堆栈的问题,16位的书上应该就讲了。32位的编程,必须首先看看32位微机原理之类的书——毕竟保护模式比实模式东西要多很多。
tjm 2001-08-04
  • 打赏
  • 举报
回复
就是说CALL之后,ESP自动指向一个返回地址,这是CALL干的好事吧,如果我不用CALL,用JMP到一个标号,来调用函数,就不会有地址如站,对吗?所以CALL就成了:
push address
jmp xxx
对吗?
那么ret干什么了?
另外,能给我一本好书吗?我是自学,已读了一本简单的书(16位,都是AX,没有EAX),看了MASM6的帮助,才能写点玩意。我的书上就没有您教的内容。
谢谢啦!
azuo_lee 2001-08-04
  • 打赏
  • 举报
回复
呵呵,我前面也写错了。你压栈的时候是a、b、c顺序,那么栈里应该是c、b、a顺序。不过假如你的函数声明为:
int _stdcall abc(int a, int b, int c);
按照STDCALL调用规则,压栈应是c、b、a顺序,这样栈里的顺序与函数声明的顺序相同,是a、b、c,就是我上面写的情况。
堆栈后来是这个样子的:
---------- <- ebp(也是esp)
保存的ebp
---------- <- ebp+4
返回地址
---------- <- ebp+8
a
---------- <- ebp+12
b
---------- <- ebp+16
c
----------
(调用者堆栈)
----------
注意上面说的是按c、b、a压栈顺序,而不是你写的a、b、c压栈顺序。
保存ebp的原因是你要使用ebp,而一般函数调用约定不更允许调用函数返回后ebp的值被更改——因为调用者也要使用ebp。另外,Windows的函数调用还隐含规定,索引寄存器edi、esi的值不允许被更改。如果你要用到,必须先保存,用完后再恢复。
返回地址其实就是调用者call指令的下一条指令地址,当执行call指令时硬件负责将其压栈,在被调函数返回执行ret指令时,由硬件负责从当前栈顶取出返回地址,并转移到返回地址继续执行——除非你明确地知道这是怎么回事,否则不要自己在程序中更改返回地址。
蚊子王 2001-08-04
  • 打赏
  • 举报
回复
是返回地址非返回值!
当调用函数(CALL FUN)时,CPU把当时的地址(IP值)压栈,再跳到函数的地址处,函数返回时,CPU再把恢复原来的地址。
tjm 2001-08-04
  • 打赏
  • 举报
回复
我打字速度太慢,又来了好老师-cui(蚊子王),我好象在哪见过这个名字,您也提到 “[ebp+4]是返回地址”,是不是我的返回直要写在这里?
tjm 2001-08-04
  • 打赏
  • 举报
回复
azuo_lee(),您真是好老师。我是新手,对堆栈更是一头雾水,以前从来不敢动用EBP,ESP,但又想把程序写成一块快的函数,象C一样,据说那样规矩。我总用寄存器传参数,这次是想写的更规矩点,就用了堆栈。天啊,看到您写的,我真是懂得太少。我先提两个问题:
1、push ebp
mov ebp, esp
之后,堆栈是不是这样:ebp(保存的ebp值)--c--b--a,
ebp=esp=栈顶地址
那么为什么[ebp+8] = a,应该是b呀?
2、[ebp+4]是返回地址是怎么回事?
3,为什么要保护ebp?
别嫌俺笨,俺看的书中没有这些东西。
蚊子王 2001-08-04
  • 打赏
  • 举报
回复
你的有以下几点错:
1、栈是后入在上面先入在下面的
2、因为申明了三个局部变量,相当于在函数开始插入了以下三句
push ebp
mov ebp, esp
sub esp, 0ch

enter 0ch,00
3、忘了还有返回地址
4、不能对两个内存地址进行mov
所以,[ebp]为前ebp值,[ebp+04h]返回地址,[ebp+08h]为c,[ebp+0ch]为b,[ebp+10h]为a

修改如下:
push a
push b
push c
call abc
mov d,eax

;;;;;;;函数abc是这样的
BeginProc abc

Local aa:DWORD
LOCAL bb:DWORD
LOCAL cc:DWORD
mov eax,dword ptr [ebp+10h]
mov aa,eax
mov eax,dword ptr [ebp+0ch]
mov bb,eax
mov eax,dword ptr [ebp+08h]
mov cc,eax
;mov aa,dword ptr [esp]
;mov bb,dword ptr [esp+4h]
;mov cc,dword ptr [esp+8h]
;;;;;;;这里是否是aa=a,bb=b,cc=c?
........
........
xor eax,eax

ret 0ch ;清栈

EndProc abc


azuo_lee 2001-08-04
  • 打赏
  • 举报
回复
不行。你用了三个local DWORD后,会有如下代码产生(或类似的代码):
push ebp
mov ebp, esp
sub esp, 12 ;为三个局部变量分配空间
此时的esp已不是进入时的esp了。更何况,不要忘了栈里面还有一个返回地址。
正确的写法是:
abc proc near
push ebp
mov ebp, esp
;sub esp, xxx ;如果需要,为局部变量分配空间

mov eax, [ebp+8] ;[ebp+8] = a,[ebp]处是保存的ebp值,[ebp+4]是返回地址
mov ebx, [ebp+12] ;[ebp+12] = b
mov ecx, [ebp+16] ;[ebp+16] = c
...

;add esp, xxx ;如果前面为局部变量分配了空间,这里要清理
pop ebp
xor eax,eax
ret 0ch ;清栈
abc endp

实际用TASM的话,有更简单的写法:
abc proc STDCALL near a:DWORD, b:DWORD, c:DWORD
mov eax, a
mov ebx, c
mov edx, d
...
ret ;汇编器自动为你生成ret 0Ch
abc endp
汇编器还会为你自动生成进入和退出时的例行代码。
用MASM也大同小异。
tjm 2001-08-04
  • 打赏
  • 举报
回复
多谢!

21,458

社区成员

发帖
与我相关
我的任务
社区描述
汇编语言(Assembly Language)是任何一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为符号语言。
社区管理员
  • 汇编语言
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧