能力值:
( LV2,RANK:10 )
|
-
-
2 楼
我记得好像是Stdcall的调用约定啊?难道我记错了?
等高人来解释吧。
《Windows环境下32位汇编语言》
3.4.2 参数传递和堆栈平衡
Win32约定的类型是StdCall,所以在程序中调用子程序或系统API后,不必自己来平衡堆栈,免去了很多麻烦。
|
能力值:
( LV9,RANK:610 )
|
-
-
3 楼
fastcall就不是啊,准确说,不完全是
|
能力值:
( LV2,RANK:10 )
|
-
-
4 楼
pascal就是stdcall,windows api的却全部都是stdcall,crt runtime当然不是。
|
能力值:
( LV3,RANK:30 )
|
-
-
5 楼
不知道就不要乱讲,少误人子弟.
windows api的却全部都是stdcall
wsprintf
C SysCall StdCall Basic Fortran Pascal
参数从左到右 是 是 是
参数从右到左 是 是 是
调用者清除堆栈 是
允许使用:VARARG 是 是 是
|
能力值:
( LV2,RANK:10 )
|
-
-
6 楼
回到Win16时代这句话就成立了
|
能力值:
( LV2,RANK:10 )
|
-
-
7 楼
你的意思是:在win16的API都是pascal调用约定的,但是在win32 api 就是stdcall调用约定?
|
能力值:
( LV2,RANK:10 )
|
-
-
8 楼
是stdcall
|
能力值:
( LV2,RANK:10 )
|
-
-
9 楼
我记得win16就是PASCAL方式调用的,win32一般就是用stdcall了
|
能力值:
( LV15,RANK:2473 )
|
-
-
10 楼
有特例的,比如wsprintf就是_cdecl
|
能力值:
( LV2,RANK:10 )
|
-
-
11 楼
[QUOTE=;]...[/QUOTE]
谢谢楼上各位:
基本上明白了。
在win16的时候,API就是pascal调用。
在win32的时候,API就是stdcall调用。如果是参数未定的,只能用cdecl调用了。
|
能力值:
( LV2,RANK:10 )
|
-
-
12 楼
不知道是你不懂还是我不懂,都说了crt的函数不算。
|
能力值:
( LV3,RANK:30 )
|
-
-
13 楼
莫非wsprintf也属crt
|
能力值:
( LV3,RANK:30 )
|
-
-
14 楼
DbgPrint
|
能力值:
( LV3,RANK:20 )
|
-
-
15 楼
WIN31时代都是真正的Pascal调用约定.
WIN32时代就都是STDCALL了.不过有宏定义PASCAL就是STDCALL.
少数不能确定参数个数和类型的API是C约定的,例如sprintf,dbgprint等
|
能力值:
( LV2,RANK:10 )
|
-
-
16 楼
.............................
|
能力值:
( LV2,RANK:10 )
|
-
-
17 楼
stdcall
1 所有参数从右至左进入堆栈
2 断点进入堆栈
3 转调用地址
4 EBP进入堆栈
5 ESP赋予EBP
6 ESP值减少n字节,n根据local 定义的局部变量来确定
7 根据uses来确定需要进入堆栈的寄存器
8 开始执行调用地址的指令
返回时
1 根据uses来确定需要弹出堆栈的寄存器
2 LEAVE指令,相当于
EBP赋予ESP(恢复ESP)
POP EBP(恢复EBP)
这样就跳过了局部变量
3 ret n (n根据参数长度决定)
这样在返回后就自动清除掉参数
用一个简单的例子来证明
;(add_1+add_2)异或(add_3+add_4)
.386
.model flat, stdcall
option casemap :none
include windows.inc
include user32.inc
includelib user32.lib
include kernel32.inc
includelib kernel32.lib
AddProc proto stdcall :dword,:dword,:dword,:dword,:dword
.data
add_1 dword 1
add_2 dword 2
add_3 dword 3
add_4 dword 4
add_sum dword ?
.code
start:
invoke AddProc,add_1,add_2,add_3,add_4,add_sum
invoke ExitProcess,NULL
AddProc proc stdcall uses esi edi ebx Op_1:dword, Op_2:dword, Op_3:dword, Op_4:dword, Op_Sum:dword
LOCAL @temp:dword
mov eax,Op_1
add eax,Op_2
mov @temp,eax
mov eax,Op_3
add eax,Op_4
xor eax,@temp
mov Op_Sum,eax
ret
AddProc endp
end start
代码是这样滴
00401000 >/$ FF35 10304000 PUSH DWORD PTR DS:[403010] ; /Arg5 = 00000000
00401006 |. FF35 0C304000 PUSH DWORD PTR DS:[40300C] ; |Arg4 = 00000004
0040100C |. FF35 08304000 PUSH DWORD PTR DS:[403008] ; |Arg3 = 00000003
00401012 |. FF35 04304000 PUSH DWORD PTR DS:[403004] ; |Arg2 = 00000002
00401018 |. FF35 00304000 PUSH DWORD PTR DS:[403000] ; |Arg1 = 00000001
0040101E |. E8 07000000 CALL temp1.0040102A ; \temp1.0040102A
00401023 |. 6A 00 PUSH 0 ; /ExitCode = 0
00401025 \. E8 26000000 CALL <JMP.&kernel32.ExitProcess> ; \ExitProcess
0040102A /$ 55 PUSH EBP
0040102B |. 8BEC MOV EBP,ESP
0040102D |. 83C4 FC ADD ESP,-4
00401030 |. 56 PUSH ESI
00401031 |. 57 PUSH EDI
00401032 |. 53 PUSH EBX
00401033 |. 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8]
00401036 |. 0345 0C ADD EAX,DWORD PTR SS:[EBP+C]
00401039 |. 8945 FC MOV DWORD PTR SS:[EBP-4],EAX
0040103C |. 8B45 10 MOV EAX,DWORD PTR SS:[EBP+10]
0040103F |. 0345 14 ADD EAX,DWORD PTR SS:[EBP+14]
00401042 |. 3345 FC XOR EAX,DWORD PTR SS:[EBP-4]
00401045 |. 8945 18 MOV DWORD PTR SS:[EBP+18],EAX
00401048 |. 5B POP EBX
00401049 |. 5F POP EDI
0040104A |. 5E POP ESI
0040104B |. C9 LEAVE
0040104C \. C2 1400 RETN 14
0040104F CC INT3
00401050 .- FF25 00204000 JMP DWORD PTR DS:[<&kernel32.ExitProcess>; kernel32.ExitProcess
|
能力值:
( LV2,RANK:10 )
|
-
-
18 楼
Win32的VC里PASCAL是一个宏,实际上还是__stdcall,参数应该从右到左压栈才对。Win16就不太清楚了,可能Win16里pascal参数是从左到右压栈吧。
|