`
zzc1684
  • 浏览: 1224532 次
  • 性别: Icon_minigender_1
  • 来自: 广州
文章分类
社区版块
存档分类
最新评论

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

 
阅读更多

接: 学 Win32 汇编[9]: 子过程中的变量声明



这是以前的一个求和函数的例子


; 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 都可以代替了.

该学模块化编程了.

分享到:
评论

相关推荐

    win32asm汇编语言-罗云彬.rar

    4. **程序设计基础**:讲解如何编写简单的汇编语言程序,包括程序结构、函数调用约定、子程序设计等。 5. **Windows API调用**:介绍了如何在汇编语言程序中调用Windows API函数,包括参数传递、错误处理、线程和...

    罗云彬--win32汇编教程源码

    这份压缩包文件是针对那些想要深入理解汇编语言,特别是针对Windows 32位平台汇编编程的初学者或进阶者准备的。 汇编语言是一种低级编程语言,它的每一个指令都直接对应于计算机硬件的机器语言。在Win32平台上,...

    x86 win32汇编学习代码(源码)

    《x86 Win32汇编学习代码》是一份针对初学者和进阶者精心整理的汇编语言学习资源,包含40至50个独立的代码实例。这些实例覆盖了x86架构下的Win32汇编语言的各个方面,旨在帮助读者深入理解汇编语言的精髓,并通过...

    Windows.环境下32位汇编语言程序设计

    编写简单的Win32控制台程序和逐步进阶到GUI程序,将帮助深化对Windows编程的理解。 9. **学习资源**:如《Windows.环境下32位汇编语言程序设计(第2版)》这样的教材,提供了详细的学习路径和实例,可以帮助初学者...

    win32 汇编 + 源代码 极品资源 罗云斌

    《win32汇编 + 源代码 极品资源 罗云斌》这个资源是专门为想要深入学习Windows环境下32位汇编语言的程序员准备的。汇编语言是计算机科学的基础,它允许程序员直接控制硬件,对于理解计算机的工作原理、优化性能以及...

    Win32汇编教程

    《Win32汇编教程》是一本专注于介绍Windows操作系统下汇编语言编程的教程,适合对计算机底层原理感兴趣的初学者和进阶者。汇编语言是计算机科学的基础,它允许程序员直接与硬件进行对话,提供了比高级语言更底层、更...

    汇编通讯1--12 合集

    win32环境下的汇编语言通常基于x86或x64架构,包括数据处理指令、控制流指令、输入/输出指令等。 4. **程序设计技巧**:在汇编语言中编写高效、可读的程序是一门艺术。这部分可能涉及流程控制、子程序设计、错误...

    win32-API-简明教程(入门学习最佳教程)

    尽管教程主要以C语言进行讲解,但大多数C++工具和一些其他语言(例如Java、汇编语言、Visual Basic)同样可以调用Win32 API。作者建议读者,如果对C语言不熟悉,应先学习C语言相关知识。同时,关于如何使用编译器,...

    Windows环境下32位汇编语言程序设计(第2版)

    总之,《Windows环境下32位汇编语言程序设计(第2版)》不仅是一本全面介绍Win32汇编语言编程的技术书籍,更是学习者探索计算机底层世界的一扇窗户。通过对本书的学习,读者不仅能掌握具体的编程技能,还能深刻理解...

    Iczelion汇编完全教程+程序实例

    《Iczelion汇编完全教程+程序实例》是一份深受IT爱好者追捧的资源,它由知名编程专家Iczelion编写,专注于讲解WIN32平台下的汇编语言编程。这份教程不仅包含了全面的理论知识,更注重实践,提供了丰富的程序实例,...

    汇编工具、dos及案例代码.zip

    在这个压缩包中,我们有两个主要的子文件:ML615.rar 和 dosbox-win32-installer.zip。 首先,ML615.rar 可能是MASM(Microsoft Macro Assembler)的一个版本,这是一个用于编写80x86架构汇编语言程序的著名汇编器...

    罗云彬书的光盘例子(N个文件夹)

    4. **内存模型与段机制**:在32位Windows中,理解数据段、代码段、堆栈段等的概念,以及如何通过段选择子和偏移地址来访问内存,对于编写有效汇编程序至关重要。 5. **寄存器的使用**:32位汇编中,EAX、EBX、ECX、...

    专业逆向人才培养模式探讨与实践.pdf

    软件逆向分析是软件安全领域的重要技术之一,它包括对软件的汇编源码进行阅读、数据结构的推断、体系结构的推测以及程序设计信息的逆向分析等。其意义不仅在于帮助我们理解软件的运行机制,更在于能够通过逆向工程...

    windows驱动开发技术详解-part2

     2.2.2 应用程序与Win32子系统  2.2.3 其他环境子系统  2.2.4 Native API  2.2.5 系统服务  2.2.6 执行程序组件  2.2.7 驱动程序  2.2.8 内核  2.2.9 硬件抽象层  2.2.10 Windows与微内核  2.3 ...

    Windows驱动开发技术详解的光盘-part1

     2.2.2 应用程序与Win32子系统  2.2.3 其他环境子系统  2.2.4 Native API  2.2.5 系统服务  2.2.6 执行程序组件  2.2.7 驱动程序  2.2.8 内核  2.2.9 硬件抽象层  2.2.10 Windows与微内核  2.3 ...

    网管教程 从入门到精通软件篇.txt

    ASM:汇编语言源文件,Pro/E装配文件 ASP:动态网页文件;ProComm Plus安装与连接脚本文件;Astound介绍文件 AST:Astound多媒体文件;ClarisWorks“助手”文件 Axx:ARJ压缩文件的分包序号文件,用于将一个大...

Global site tag (gtag.js) - Google Analytics