汇编程序的多模块化
来源:互联网 发布:mac os 分辨率设置 编辑:程序博客网 时间:2024/05/21 11:22
在此章节之前,创建的程序全部是只用一个模块的,也就是程序中只用了一个END指令,这里通过创建ArraySum例子程序演示创建多模块程序的方法。
下面是这个程序运行的结果:
首先通过使用ENTERN伪指令创建传统的多模块程序,这里的ENTERN伪指令实际上只起了调用其他模块里的过程前对此过程的声明作用。这里的被调用过程与一个模块表达式没有书写格式上的变化,源程序如下:
(_prompt.asm模块)
- TITLE Prompt For Integers (_prompt.asm)
- INCLUDE Irvine32.inc
- .code
- ;----------------------------------------------------
- PromptForIntegers PROC
- ; 提示用户输入三个整数,调用ReadInt读取输入返回到eax中,
- ; 然后把值插入到数组中.
- ; 参数:
- ; ptrPrompt:PTR BYTE ; 提示用户的字符串
- ; ptrArray:PTR DWORD ; 数组首地址
- ; arraySize:DWORD ; 数组的长度
- ; 返回值:无
- ;-----------------------------------------------------
- arraySize EQU [ebp+16]
- ptrArray EQU [ebp+12]
- ptrPrompt EQU [ebp+8] ; [ebp+8]指向调用此模块(call指令)之前的入栈数据
- enter 0,0
- ; enter指令自动为被调用过程创建堆栈框架(此处相当于push ebp;mov ebp,esp;sub esp,0),
- ; 并为局部变量创建堆栈空间(enter 0,0 前一个0表示局部变量占用的字节数,
- ; 后一个0表示从调用过程复制到当前堆栈框架中的堆栈框架指针的数目)
- pushad ; 8个通用寄存器入栈
- mov ecx,arraySize ; ecx表示数组的大小,这里同时是循环计数器
- cmp ecx,0 ; 循环计数器 <= 0?
- jle L2 ; 是:跳过循环体
- mov edx,ptrPrompt ; 否:把提示字符串首地址传递给edx
- mov esi,ptrArray ; esi指向数组的首地址
- L1: call WriteString ; 预先定义的过程,输出edx代表的字符串
- call ReadInt ; 等待用户输入后,从标准输入中读取一个32位有符号整数并在eax中返回
- call Crlf
- mov [esi],eax ; 把输入的值存储在数组中
- add esi,4 ; esi指向数组下一个元素
- loop L1
- L2: popad ; 8个通用寄存器出栈
- leave
- ; leave指令释放一个过程的堆栈框架,执行与enter相反的动作(此处相当于mov esp,ebp;pop ebp)
- ; 如果enter指令创建了局部变量,leave还要释放局部变量占用的堆栈空间
- ret 12
- ; 调用此模块前,主模块会把此模块用到的相应参数入栈,这里12表示此模块结束后释放主模块中占用的堆栈空间
- ; 相当于依次执行ret;add esp,12的指令
- PromptForIntegers ENDP
- END
(_arrysum.asm模块):
- TITLE ArraySum Procedure (_arrysum.asm)
- INCLUDE Irvine32.inc
- .code
- ArraySum PROC
- ;
- ; 计算有符号32位整数数组的各元素总和
- ; 参数:
- ; ptrArray ; 指向数组首地址
- ; arraySize ; 数组的长度(DWORD)
- ; 返回值: EAX = sum
- ;-----------------------------------------------------
- ptrArray EQU [ebp+8]
- arraySize EQU [ebp+12]
- enter 0,0 ; enter指令创建堆栈框架,此处无局部变量
- push ecx ; 提示:eax作为返回值,不能入栈
- push esi
- mov eax,0 ; 初始化数组总和为0
- mov esi,ptrArray ; 数组首地址
- mov ecx,arraySize ; 数组大小,同时是循环计数器
- cmp ecx,0 ; 循环计数器 <= 0?
- jle L2 ; 是: 跳过循环体
- L1: add eax,[esi] ; 否:把数组一个元素加到eax中
- add esi,4 ; 指向下一个数组元素
- loop L1
- L2: pop esi
- pop ecx ; 总和通过eax返回到调用过程(主模块)
- leave ; 释放enter创建的堆栈框架
- ret 8 ; 释放调用过程中(主模块)的参数通过堆栈传递时占用的堆栈空间
- ArraySum ENDP
- END
(_display.asm模块):
- TITLE DisplaySum Procedure (_display.asm)
- INCLUDE Irvine32.inc
- .code
- ;-----------------------------------------------------
- DisplaySum PROC
- ; 在控制台窗口中显示总和的值
- ; 参数:
- ; ptrPrompt ; 提示字符串首地址
- ; theSum ; 数组各元素总和(DWORD)
- ; 返回值: 无
- ;-----------------------------------------------------
- theSum EQU [ebp+12]
- ptrPrompt EQU [ebp+8]
- enter 0,0 ; enter指令创建堆栈框架,此处无局部变量
- push eax
- push edx
- mov edx,ptrPrompt ; 预先定义的过程参数
- call WriteString ; 输出提示字符串到屏幕
- mov eax,theSum ; 预先定义的过程参数
- call WriteInt ; 输出数组总和到屏幕
- call Crlf
- pop edx
- pop eax
- leave
- ret 8 ; 返回到主模块并释放主模块调用此过程时占用的堆栈空间
- DisplaySum ENDP
- END
(Sum_main.asm主模块):
- TITLE Integer Summation Program (Sum_main.asm)
- ; 多模块程序例子: (主模块/启动模块)
- ; 这个程序提示用户输入3个32位有符号整数,
- ; 然后把输入的整数存储到数组中并计算这个数组的总和,
- ; 显示数组的总和到屏幕
- INCLUDE Irvine32.inc ;INCLUDE 伪指令包含用户定义的.inc文件,其中可集中放置变量或过程的声明等信息
- EXTERN PromptForIntegers@0:PROC ; EXTERN 伪指令在调用外部模块中的过程前声明,@0表示PromptForIntegers过程没有PROC伪指令参数
- EXTERN ArraySum@0:PROC, DisplaySum@0:PROC ; EXTERN 伪指令在调用外部模块中的过程前声明,其余同上
- ; 为被调用过程赋予其他的标号,方便主模块调用
- ArraySum EQU ArraySum@0
- PromptForIntegers EQU PromptForIntegers@0
- DisplaySum EQU DisplaySum@0
- Count = 3 ; 标号代表定义数组的大小
- .data
- prompt1 BYTE "Enter a signed integer: ",0
- prompt2 BYTE "The sum of the integers is: ",0
- array DWORD Count DUP(?) ; 定义包含count个元素的未初始化数组
- sum DWORD ?
- .code
- main PROC
- call Clrscr ; 清理屏幕
- ; 调用PromptForIntegers( addr prompt1, addr array, Count ),括号中为向被调用过程包含的参数
- push Count
- push OFFSET array
- push OFFSET prompt1
- call PromptForIntegers
- ; 调用eax = ArraySum( addr array, Count ),其中eax是被调用过程的返回值
- push Count
- push OFFSET array
- call ArraySum
- mov sum,eax
- ; 调用DisplaySum( addr prompt2, sum )
- push sum
- push OFFSET prompt2
- call DisplaySum
- call Crlf
- exit
- main ENDP
- END main
下面是这个程序运行的结果:
0 0
- 汇编程序的多模块化
- 多模块汇编程序的组织
- 汇编程序多个数据段的使用
- StoryBoard的多模块化管理
- 汇编程序的优化问题
- 自写的汇编程序
- 汇编程序的基本结构
- 计时器的汇编程序问题
- 汇编程序的一般框架
- 汇编程序的组成
- 万年历的汇编程序
- 汇编程序的组成
- 简单的汇编程序解读
- 简单的汇编程序应用
- 简单的汇编程序
- 毁掉自己的汇编程序
- 汇编程序:红红绿绿的字符
- 汇编程序:简单的菜单
- Android开发笔记---Manifest的android:windowSoftInputMode属性说明
- 数据结构 二叉树的非递归遍历
- 错误 是否保存对以下各项的更改 devenv.sin
- 字符串哈希算法
- 程序员必知(四):找次品
- 汇编程序的多模块化
- 合泰 HT66F30 定时器初始化
- inux 学习书目推荐
- 数据结构 二叉树的线索存储
- 面积
- java类中打印信息乱码?
- 第16周项目2-指来指去(2)
- 邮票问题
- 表达式求值