《Inter汇编语言程序设计》8.6 创建多模块程序(INVOKE PROTO)

来源:互联网 发布:淘宝资源怎么找 编辑:程序博客网 时间:2024/06/11 07:24

继续上此的多模块创建...

INVOKE与PROTO伪指令隐藏了大量的细节,程序的书写格式发生了不少变化。但是有一点,无论是ENTERN创建的还是INVOKE  PROTO创建的,经过编译连接后生成的机器码是一样的..

(_prompt.asm模块):

TITLE Prompt For Integers      (_prompt.asm)INCLUDE Irvine32.inc.code;----------------------------------------------------PromptForIntegers PROC,ptrPrompt:PTR BYTE,; PROC指令的参数1,相当于传统伪指令中的ptrPromptEQU [ebp+8]       ptrArray:PTR DWORD,; PROC指令的参数2,相当于传统伪指令中的ptrArrayEQU [ebp+12] arraySize:DWORD; PROC指令的参数3,相当于传统伪指令中的arraySizeEQU [ebp+16]; 提示用户输入三个整数,调用ReadInt读取输入返回到eax中,; 然后把值插入到数组中.; 参数:;紧跟在PROC指令后面;      (PROC指令的参数也就是本过程的参数,在参数与PROC指令间不能有间断,而且要注意PROC指令的书写存在逗号);PROC指令也为局部变量分配堆栈空间并在使用结束后释放此堆栈空间,相当于enter与leave指令; 返回值:无;-----------------------------------------------------pushad; 8个通用寄存器入栈movecx,arraySize; ecx表示数组的大小,这里同时是循环计数器cmpecx,0; 循环计数器 <= 0?jleL2; 是:跳过循环体movedx,ptrPrompt; 否:把提示字符串首地址传递给edxmovesi,ptrArray; esi指向数组的首地址L1:callWriteString; 预先定义的过程,输出edx代表的字符串callReadInt; 等待用户输入后,从标准输入中读取一个32位有符号整数并在eax中返回callCrlfmov[esi],eax; 把输入的值存储在数组中addesi,4; esi指向数组下一个元素loopL1L2:popad; 8个通用寄存器出栈ret; 注意这里ret后的常量参数也不见了,PROC伪指令会编译后自动生成这些东西PromptForIntegers ENDPEND

(_arrysum.asm模块):

TITLE ArraySum Procedure             (_arrysum.asm)INCLUDE Irvine32.inc.code;-----------------------------------------------------ArraySum PROC,ptrArray:PTR DWORD,; PROC指令的参数1,相当于传统伪指令中的ptrArrayEQU [ebp+8]arraySize:DWORD; PROC指令的参数2,相当于传统伪指令中的arraySizeEQU [ebp+12]; 计算有符号32位整数数组的各元素总和; 参数:;紧跟在PROC指令后面;      (PROC指令的参数也就是本过程的参数,在参数与PROC指令间不能有间断,而且要注意PROC指令的书写存在逗号);PROC指令也为局部变量分配堆栈空间并在使用结束后释放此堆栈空间,相当于enter与leave指令; 返回值:  EAX = sum;-----------------------------------------------------pushecx; 提示:eax作为返回值,不能入栈pushesimoveax,0; 初始化数组总和为0movesi,ptrArray; 数组首地址movecx,arraySize; 数组大小,同时是循环计数器cmpecx,0; 循环计数器 <= 0?jleL2; 是: 跳过循环体L1:addeax,[esi]; 否:把数组一个元素加到eax中addesi,4; 指向下一个数组元素loopL1L2:popesipopecx; 总和通过eax返回到调用过程(主模块)ret; 注意这里ret后的常量参数也不见了,PROC伪指令会编译后自动生成这些东西ArraySum ENDPEND

(_display.asm模块):

TITLE DisplaySum Procedure(_display.asm)INCLUDE Irvine32.inc.code;-----------------------------------------------------DisplaySum PROC,ptrPrompt:PTR BYTE,; PROC指令的参数1,相当于传统伪指令中的ptrPromptEQU [ebp+8]theSum:DWORD; PROC指令的参数2,相当于传统伪指令中的theSumEQU [ebp+12]; 在控制台窗口中显示总和的值; 参数:;PROC指令也为局部变量分配堆栈空间并在使用结束后释放此堆栈空间,相当于enter与leave指令; 返回值: 无;-----------------------------------------------------pusheaxpushedxmovedx,ptrPrompt; 预先定义的过程参数callWriteString; 输出提示字符串到屏幕moveax,theSum; 预先定义的过程参数callWriteInt; 输出数组总和到屏幕callCrlfpopedxpopeaxret8; 返回到主模块并释放主模块调用此过程时占用的堆栈空间DisplaySum ENDPEND

(Sum_main.asm主模块):

TITLE Integer Summation Program (Sum_main.asm); 多模块程序例子:   (主模块/启动模块); 这个程序提示用户输入3个32位有符号整数,; 然后把输入的整数存储到数组中并计算这个数组的总和,; 显示数组的总和到屏幕INCLUDE Irvine32.inc;INCLUDE 伪指令包含用户定义的.inc文件,其中可集中放置变量或过程的声明等信息PromptForIntegers PROTO,ptrPrompt:PTR BYTE,ptrArray:PTR DWORD,arraySize:DWORDArraySum PROTO,ptrArray:PTR DWORD,count:DWORDDisplaySum PROTO,ptrPrompt:PTR BYTE,theSum:DWORD; 以上是PROTO伪指令为被调用过程创建的原型,作用是在INVOKE伪指令调用这些过程前声明此过程; 本例子PROTO指令不可以省略,因为这些过程创建之后才使用INVOKE指令调用的Count = 3; 标号代表定义数组的大小.dataprompt1 BYTE  "Enter a signed integer: ",0prompt2 BYTE  "The sum of the integers is: ",0array   DWORD  Count DUP(?); 定义包含count个元素的未初始化数组sum     DWORD  ?.codemain PROCcallClrscr; 清理屏幕INVOKE PromptForIntegers, ADDR prompt1, ADDR array, Count; 调用PromptForIntegers过程并向其传递参数,addr表示传递的为地址INVOKE ArraySum, ADDR array, Count; 调用ArraySum过程并向其传递参数,eax是被调用过程的返回值movsum,eaxINVOKE DisplaySum, ADDR prompt2, sum; 调用DisplaySum过程并向其传递参数callCrlfexitmain ENDPEND main

下面是这个程序运行的结果: