文档章节

学 Win32 汇编[32] - 子程序进阶

涂孟超
 涂孟超
发布于 2014/09/26 15:35
字数 1170
阅读 12
收藏 0

接: http://www.cnblogs.com/del/archive/2010/04/05/1704864.html

这是以前的一个求和函数的例子
; Test32_1.asm
.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

 
 
 
 
 

 

 

  

把上面的例子改为用寄存器传递参数:
; Test32_2.asm
.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 提前声明:
; Test32_3.asm
.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 是从左到右压栈参数.
; Test32_4.asm
.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 的下偏移? 因为是先压栈参数在调用函数.
; Test32_5.asm
.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 能更好地理解压参顺序:
; Test32_6.asm
.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 保护寄存器:
所谓保护就是在子过程执行前先压栈, 执行后在出栈.
; Test32_7.asm
.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 来得简洁:
; Test32_8.asm
.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 都可以代替了.

该学模块化编程了.

本文转载自:http://www.cnblogs.com/del/archive/2010/04/26/1721193.html

共有 人打赏支持
涂孟超
粉丝 12
博文 2011
码字总数 14107
作品 0
深圳
程序员
私信 提问
Win32汇编开发环境介绍和RadAsm简明教程

Win32汇编开发环境介绍和RadAsm简明教程 现在很多朋友都在学习汇编语言,一方面汇编语言是大学计算机课程的必修课,另一方面则是为了从其它语言转到汇编语言来,无论什么原因,我认为学习汇编...

nothingfinal
2009/08/01
0
0
[Beautifulzzzz的博客目录] 快速索引点这儿O(∩_∩)O~~,红色标记的是不错的(⊙o⊙)哦~

3D相关开发 [direct-X] 1、direct-X最小框架 [OpenGL] 1、环境搭建及最小系统 [OpenGL] 2、企业版VC6.0自带的Win32-OpenGL工程浅析 51单片机 [51单片机] 1602液晶显示控制代码 [51单片机] 1...

史迪奇2号
2017/08/01
0
0
win32汇编和x64汇编?

win32汇编升到winx64汇编,转型容易吗?我指的是会win32汇编,还学x64汇编吗?我是初学,能不能直接学x64汇编语言,请推荐本书?

IIOWE
2014/10/01
840
3
为什么破解要学win32汇编?

听说破解要学win32汇编,写壳也要用win32汇编?为什么呢?不学不能学破解吗?

IIOWE
2014/10/02
2.4K
13
MASM32 SDK

MASM32 SDK是不同工具软件的大集合,它的汇编编译器用的是微软MASM软件包中的Ml.exe,资源编译器和32位链接器使用的是Microsoft Visual Studio中的Rc.exe和Link.exe,同时包含了Microsoft V...

匿名
2011/05/04
5.9K
1

没有更多内容

加载失败,请刷新页面

加载更多

HTTP状态码对照表(HTTP response codes)

由于博主工作最近在做大数据日志分析的时候,用到了很多http状态码相关的知识。博主基本只记得其中200和404两个,所以,在此做个笔录。 当浏览者访问一个网页时,浏览者的浏览器会向网页所在...

em_aaron
8分钟前
0
0
java 反射

基本概念 RTTI,即Run-Time Type Identification,运行时类型识别。RTTI能在运行时就能够自动识别每个编译时已知的类型。   要想理解反射的原理,首先要了解什么是类型信息。Java让我们在运...

细节探索者
19分钟前
0
0
推荐转载连接

https://www.cnblogs.com/ysocean/p/7409779.html#_label0

小橙子的曼曼
44分钟前
0
0
雷军亲自打造的套餐了解下:用多少付多少

12月28日消息,小米科技创始人兼CEO雷军微博表示,小米移动任我行套餐方案,原则上就是明明白白消费,用多少付多少,不用不花钱!上网、电话和短信都是一毛钱,上网0.1元/M,电话0.1元/分钟,...

linuxCool
56分钟前
0
0
协议简史:如何学习网络协议?

大学时,学到网络协议的7层模型时,老师教了大家一个顺口溜:物数网传会表应。并说这是重点,年年必考,5分的题目摆在这里,你们爱背不背。 考试的时候,果然遇到这个问题,搜索枯肠,只能想...

Java干货分享
今天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部