本节主要讲解使用传统的 EXTERN 伪指令引用位于不同模块中的函数。
jprompt.asm 是 PromptForIntegers 过程的源代码文件。它显示提示要求用户输入三个整数,调用 Readlnt 获取数值,并将它们插入数组:
;提示整数输入请求 (_prompt.asm)
INCLUDE Irvine32.inc
.code
;--------------------------------
PromptForIntegers PROC
;提示用户为数组输入整数,并用
;用户输入填充该数组。
;接收:
; ptrPrompt:PTR BYTE ;提示信息字符串
; ptrArray:PTR DWORD ;数组指针
; arraySize:DWORD ;数组大小
;返回:无
;--------------------------------
arraySize EQU [ebp+16]
ptrArray EQU [ebp+12]
ptrPrompt EQU [ebp+8]
enter 0,0
pushad ;保存全部寄存器
mov ecx,arraySize
cmp ecx,0 ;数据大小WO?
jle L2 ;是:退出
mov edx,ptrPrompt ;提示信息的地址
mov esi,ptrArray
L1: call WriteString ;显示字符串
call ReadInt ;将整数读入EAX
call Crlf ;换行
mov [esi],eax ;保存入数组
add esi,4 ;下一个整数
loop L1
L2: popad ;恢复全部寄存器
leave
ret 12 ;恢复堆栈
PromptForIntegers ENDP
END
_arraysum.asm 模块为 ArraySum 过程,计算数组元素之和,并用 EAX 返回计算结果:
;ArraySumit程 (_arrysum.asm)
INCLUDE Irvine32.inc
.code
;----------------------------------------------
ArraySum PROC
;计算32位整数数组之和。
;接收:
; ptrArray ;数组指针
; arraySize ;数组大小(DWROD)
;返回:EAX = 和数
;----------------------------------------------
ptrArray EQU [ebp+8]
arraySize EQU [ebp+12]
enter 0,0
push ecx ;EAX 不入栈
push esi
mov eax, 0 ;和数清零
mov esi, ptrArray
mov ecx,arraySize
cmp ecx, 0 ;数组大小WO?
jle L2 ;是:退出
L1: add eax, [esi] ;将每个整数加到和数中
add esi,4 ;指向下一个整数
loop L1 ;按数组大小重复
L2: pop esi
pop ecx ;用EAX返回和数
leave
ret 8 ;恢复堆栈
ArraySum ENDP
END
_display.asm 模块为 DisplaySum 过程,显示标号和和数的结果:
;DisplaySum 过程 (_display.asm)
INCLUDE Irvine32.inc
.code
;-----------------------------------------
DisplaySum PROC
;在控制台显示和数。
;接收:
; ptrPrompt ;提示字符串的偏移量
; theSum ;数组和数(DWROD)
;返回:无
;-----------------------------------------
theSum EQU [ebp+12]
ptrPrompt EQU [ebp+8]
enter 0,0
push eax
push edx
mov edx,ptrPrompt ;提示字符串的指针
call WriteString
mov eax,theSum
call Writelnt ;显示 EAX
call Crlf
pop edx
pop eax
leave
ret 8 ;恢复堆栈
DisplaySum ENDP
END
Sum_main.asm 模块为启动过程 (main)。其中的 EXTERN 伪指令指定了三个外部过程。为了使源代码更加友好,用 EQU 伪指令再次定义了过程名:
每次过程调用之前,用注释说明了参数顺序。该过程使用 STDCALL 参数传递规范:
;整数求和过程(Sum_main.asm)
;多模块示例
;本程序由用户输入多个整数,
;将它们存入数组,计算数组之和,
;并显示和数。
INCLUDE Irvine32.inc
EXTERN PromptForIntegers@0:PROC
EXTERN ArraySum@0:PROC, DisplaySum@0:PROC
;为方便起见,重新定义外部符号
ArraySum EQU ArraySum@0
PromptForIntegers EQU PromptForIntegers@0
DisplaySum EQU DisplaySum@0
;修改 Count 来改变数组大小:
Count = 3
.data
prompt1 BYTE "Enter a signed integer: ",0
prompt2 BYTE "The sum of the integers is: ",0
array DWORD Count DUP(?)
sum DWORD ?
.code
main PROC
call Clrscr
;PromptForIntegers (addr prompt1, addr array, Count)
push Count
push OFFSET array
push OFFSET prompt1
call PromptForIntegers
;sum = ArraySum(addr array, Count)
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