• 汇编语言用Extern伪指令新建模块[附带实例]

    本节主要讲解使用传统的 EXTERN 伪指令引用位于不同模块中的函数。

    PromptForIntegers

    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

    _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

    DisplaySum

    _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

    Startup 模块

    Sum_main.asm 模块为启动过程 (main)。其中的 EXTERN 伪指令指定了三个外部过程。为了使源代码更加友好,用 EQU 伪指令再次定义了过程名:

    ArraySum           EQU ArraySum@0
    PromptForIntegers  EQU PromptForIntegers@0
    DisplaySum         EQU DisplaySum@0

    每次过程调用之前,用注释说明了参数顺序。该过程使用 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

更多...

加载中...