Win32ASM学习[20]:子程序
关于函数调用约定 :函数调用约定
这是以前的一个求和函数的例子
----------------------------------------------------------------------------------------------------------------
.386
.model flat, stdcall
include windows.inc
include kernel32.inc
include masm32.inc
include debug.inc
includelib kernel32.lib
includelib masm32.lib
includelib debug.lib
.code
sum proc v1:dword, v2:dword, v3:dword
mov eax, v1
add eax, v2
add eax, v3
ret
sum endp
;
main proc
invoke sum, 11, 22, 33
PrintDec eax; 66
ret
main endp
end main
----------------------------------------------------------------------------------------------------------------
把上面的例子改为用寄存器传递参数:
----------------------------------------------------------------------------------------------------------------
.386
.model flat, stdcall
include windows.inc
include kernel32.inc
include masm32.inc
include debug.inc
includelib kernel32.lib
includelib masm32.lib
includelib debug.lib
.code
sum proc
add eax, ecx
add eax, edx
ret
sum endp
;
main proc
mov eax, 11
mov ecx, 22
mov edx, 33
invoke sum
PrintDec eax; 66
ret
main endp
end main
----------------------------------------------------------------------------------------------------------------
如果调用的函数在之后实现, 须用 PROTO 提前声明:
----------------------------------------------------------------------------------------------------------------
.386
.model flat, stdcall
include windows.inc
include kernel32.inc
include masm32.inc
include debug.inc
includelib kernel32.lib
includelib masm32.lib
includelib debug.lib
;sum proto v1:dword, v2:dword, v3:dword
sum proto :dword, :dword, :dword ;函数声明的主要是参数类型, 一般省略参数名
.code
main proc
invoke sum, 11, 22, 33 ;现在调用的是之后的函数
PrintDec eax; 66
ret
main endp
;
sum proc v1, v2, v3
mov eax, v1
add eax, v2
add eax, v3
ret
sum endp
end main
----------------------------------------------------------------------------------------------------------------
测试 StdCall 模式下的参数压栈顺序:
----------------------------------------------------------------------------------------------------------------
子程序可以指定语言模式(StaCall、C、SysCall、Basic、Fortran、Pascal);
如果不指定则默认使用在 .model 中指定的语言模式.
StaCall、C、SysCall 是从右到左压栈参数;
Basic、Fortran、Pascal 是从左到右压栈参数.
----------------------------------------------------------------------------------------------------------------
.386
.model flat, stdcall
include windows.inc
include kernel32.inc
include masm32.inc
include debug.inc
includelib kernel32.lib
includelib masm32.lib
includelib debug.lib
.code
sum proc stdcall v1, v2, v3
;查看参数压栈顺序(StdCall 是从右到左 push)
mov edx, [ebp+16]
PrintHex edx ;33
mov edx, [ebp+12]
PrintHex edx ;22
mov edx, [ebp+8]
PrintHex edx ;11
PrintLine
;下面求和代码
mov eax, v1
add eax, v2
add eax, v3
ret
sum endp
;
main proc
invoke sum, 11h, 22h, 33h
PrintDec eax; 66
ret
main endp
end main
----------------------------------------------------------------------------------------------------------------
测试 Pascal 模式下的参数压栈顺序:
----------------------------------------------------------------------------------------------------------------
这是和上面的对比练习, 它们的压栈参数的顺序是反的.
其中的 EBX+8 是最后压栈参数(DWORD)的地址, 同样 EBX 向上偏移 12、16 就分别是另外两个参数的地址.
地址 EBX+4 是 RET 将要返回的地址.
为什么参数不是在 EBX 的下偏移? 因为是先压栈参数在调用函数.
----------------------------------------------------------------------------------------------------------------
.386
.model flat, stdcall
include windows.inc
include kernel32.inc
include masm32.inc
include debug.inc
includelib kernel32.lib
includelib masm32.lib
includelib debug.lib
.code
sum proc pascal v1, v2, v3
;查看参数压栈顺序(pascal 是从左到右 push)
mov edx, [ebp+16]
PrintHex edx ;11
mov edx, [ebp+12]
PrintHex edx ;22
mov edx, [ebp+8]
PrintHex edx ;33
PrintLine
;下面求和代码
mov eax, v1
add eax, v2
add eax, v3
ret
sum endp
;
main proc
invoke sum, 11h, 22h, 33h
PrintDec eax; 66
ret
main endp
end main
----------------------------------------------------------------------------------------------------------------
如果用 Call 代替 invoke 能更好地理解压参顺序:
----------------------------------------------------------------------------------------------------------------
.386
.model flat, stdcall
include windows.inc
include kernel32.inc
include masm32.inc
include debug.inc
includelib kernel32.lib
includelib masm32.lib
includelib debug.lib
.code
ViewParam proc C v1, v2, v3 ;把这里的 C 换为 pascal 会有完全不同的结果
PrintDec v1 ;11
PrintDec v2 ;22
PrintDec v3 ;33
ret
ViewParam endp
;
main proc
push 33
push 22
push 11
call ViewParam
leave ;leave 是上面几个 push 的反操作, 省了不少 pop
ret
main endp
end main
----------------------------------------------------------------------------------------------------------------
子过程使用 uses 保护寄存器:
----------------------------------------------------------------------------------------------------------------
所谓保护就是在子过程执行前先压栈, 执行后在出栈.
----------------------------------------------------------------------------------------------------------------
.386
.model flat, stdcall
include windows.inc
include kernel32.inc
include masm32.inc
include debug.inc
includelib kernel32.lib
includelib masm32.lib
includelib debug.lib
.data
dwVal dd ?
.code
sum proc stdcall uses eax ecx edx, v1, v2, v3 ;这其中的 stdcall 可省略
mov eax, v1
mov ecx, v2
mov edx, v3
add eax, ecx
add eax, edx
mov dwVal, eax
ret
sum endp
;
main proc
;sum 对这三个寄存器进行的保护, 先给些测试值
mov eax, 7
mov ecx, 8
mov edx, 9
invoke sum, 11, 22, 33
PrintDec dwVal ;66
PrintDec eax ;7
PrintDec ecx ;8
PrintDec edx ;9
ret
main endp
end main
----------------------------------------------------------------------------------------------------------------
使用 uses 不如使用 pushad 和 popad 来得简洁:
----------------------------------------------------------------------------------------------------------------
.386
.model flat, stdcall
include windows.inc
include kernel32.inc
include masm32.inc
include debug.inc
includelib kernel32.lib
includelib masm32.lib
includelib debug.lib
.data
dwVal dd ?
.code
sum proc v1, v2, v3
pushad
mov eax, v1
mov ecx, v2
mov edx, v3
add eax, ecx
add eax, edx
mov dwVal, eax
popad
ret
sum endp
;
main proc
mov eax, 7
mov ecx, 8
mov edx, 9
invoke sum, 11, 22, 33
PrintDec dwVal ;66
PrintDec eax ;7
PrintDec ecx ;8
PrintDec edx ;9
ret
main endp
end main
----------------------------------------------------------------------------------------------------------------
和子程序密切相关的有两个指令: call 和 ret
call 相当于 push+jmp;
ret 相当于 pop+jmp;
有些 ret 后面还有个数字, 如 ret 8, 这相当于 ret 后再 esp+8(这是清理 8 字节的堆栈).
另外程序可以同 public 和 private 指定是否能跨模块使用, 默认是 public, 极少用到 private.
声明其他模块成员的 extrn、extern、public 关键字, 现在用 proto 都可以代替了.
Win32ASM学习[20]:子程序相关推荐
- 10以内数的组成分解图_学前儿童如何学习20以内的加减法,收藏了
学前儿童如何学习20以内的加减法,收藏了 20以内的数的分成及加减法,是幼儿对数与量的基本认识.是幼儿园教材中的学习内容.如何教好"20以内的加法"呢?我在这里谈几点学习20以内的 ...
- 深度学习-20:神经科学、脑科学和稀疏特性
深度学习-20:神经科学.脑科学和稀疏特性 深度学习原理与实践(开源图书)-总目录,建议收藏,告别碎片阅读! 第二次世界大战之后,美苏在全维度展开了霸权竞赛,人工智能研究伴随着计算机的发展也开始进入佳 ...
- STC15F104W无线收发模块,源程序注释很详细,PDF格式说明书,可以学习20个遥控器,3个按键一个学习按键还有按键开和按键关
STC15F104W无线收发模块,源程序注释很详细,PDF格式说明书,可以学习20个遥控器,3个按键一个学习按键还有按键开和按键关,遥控器也能控制开关,用充电宝或手机充电器供电都行,频率433和315 ...
- for循环10000次花多长时间_我的三菱FX PLC学习之子程序调用与循环
戳上方蓝字 "技成电工课堂" 关注我们哦! 上次,我们学习了程序流程转移中的条件跳转CJ,这次,我们接着向子程序调用CALL和FOR循环发起进攻吧! 显然,子程序调用CALL和FO ...
- Win32ASM学习[21]:宏汇编(1)
---------------------------------------------------------------------------------------------------- ...
- 【机器学习】深度学习20个笔试题
请不要在题上写画答案,写在答题纸上 假设你训练SVM后,得到一个线性决策边界,你认为该模型欠拟合.在下次迭代训练模型时,应该考虑: A.增加训练数据 B.减少训练数据 C.计算更多变量 D.减少特征 ...
- 深度学习(20):nerf论文翻译与学习
目录 1 Introduction 2 Related Work 3 Neural Radiance Field Scene Representation 4 Volume Rendering wit ...
- Javascript基础学习20问(二)
1.函数(方法):封装执行一项专门任务的步骤的代码序列-->重用 2.参数:方法内独有的变量,接受传入数据,在方法中处理 3.作用域:一个变量的可用范围 全局作用域:全局变量 局 ...
- Win32ASM学习[12]:位测试指令位扫描指令
---------------------------------------------------------------------------------------------------- ...
最新文章
- Android Studio导入Eclipse项目的两种方法
- H.265的NALU
- ExtJs中column与form布局的再次领悟
- 使用舵机PWM信号控制直流电机的转动
- android 屏幕录像
- CV之FDFA:利用MTCNN的脚本实现对LFW数据集进行FD人脸检测和FA人脸校准
- 统计通话次数和时间的软件_通话时间统计app下载|通话时间统计安卓版下载 v1.0.3 - 跑跑车安卓网...
- 23 WM配置-策略-入库策略3-定义现有库存的附加策略I(Addition to Existing Stock Strategy)
- 2021亳州高考成绩查询,2021年亳州高考状元名单公布,亳州文理科状元是谁多少分...
- View与Model绑定注意事项 (视图无数据显示)
- 基于源码编译安装openssh
- mysql字段长度的作用_数据库字段的长度 作用
- python3出现TypeError: can only concatenate str (not bytes) to str的错误,大一刚上手python的学习,望大神解决。感激不尽
- 工业电脑量产测试之----U盘DOS 启动盘制作(1)
- 掠食细菌—蛭弧菌B. bacteriovorus,可以对抗革兰氏阴性感染?
- [附源码]java毕业设计基于的高校学生考勤管理系统
- 微软同步备份工具SyncToy,值得使用
- Note: LSR LER
- Testin云测技术沙龙在沪召开,云监控预警成关注重点
- view \function\行转列的方法。