• 汇编语言FWAIT(WAIT)指令:异常同步

    整数 (CPU) 和 FPU 是相互独立的单元,因此,在执行整数和系统指令的同时可以执行浮点指令。这个功能被称为并行性 (concurrency),当发生未屏蔽的浮点异常时,它可能是个潜在的问题。反之,已屏蔽异常则不成问题,因为,FPU 总是可以完成当前操作并保存结果。

    发生未屏蔽异常时,中断当前的浮点指令,FPU 发异常事件信号。当下一条浮点指令或 FWAIT(WAIT) 指令将要执行时,FPU 检查待处理的异常。如果发现有这样的异常,FPU 就调用浮点异常处理程序(子程序)。

    如果引发异常的浮点指令后面跟的是整数或系统指令,情况又会是怎样的呢?很遗憾,指令不会检查待处理异常,它们会立即执行。假设第一条指令将其输出送入一个内存操作数,而第二条指令又要修改同一个内存操作数,那么异常处理程序就不能正确执行。示例如下:

    .data
    intVal DWORD 25
    .code
    fild intVal  ;将整数加载到 ST(0)
    inc intVal  ;整数加 1

    设置 WAIT 和 FWAIT 指令是为了在执行下一条指令之前,强制处理器检查待处理且未屏蔽的浮点异常。这两条指令中的任一条都可以解决这种潜在的同步问题,直到异常处理程序结束,才执行 INC 指令。

    fild intVal  ;将整数加载到 ST(0)
    fwait         ;等待待处理异常
    inc intVal  ;整数加 1

    下面将用几个简短的例子来演示浮点算术运算指令。一个很好的学习方法是用 C++ 编写表达式,编译后,再检查由编译器生成的代码。

    表达式

    现在编写代码,计算表达式 valD=-valA+(valB*valC)。下面给出一种可能的循序渐进的方法:将 valA 加载到堆栈,并取其负数;将 valB 加载到 ST(0),则 valA 成为 ST(1);将 ST(0) 和 valC 相乘,乘积保存在 ST(0) 中;将 ST(1) 与 ST(0) 相加,和数保存到 valD:

    .data
    valA REAL8 1.5
    valB REAL8 2.5
    valC REAL8 3.0
    valD REAL8 ?; +6.0
    .code
    fld valA    ; ST(0) = valA
    fchs        ;修改 ST(0) 的符号
    fld valB    ; 将 valB 加载到 ST(0)
    fmul valC   ; ST(0) *= valC
    fadd        ; ST(0) += ST(1)
    fstp valD   ; 将 ST(0) 保存到 valD

    数组求和

    下面的代码计算并显示一个双精度实数数组之和:

    ARRAY_SIZE = 20
    .data
    sngArray REAL8 ARRAY_SIZE DUP(?)
    .code
        mov    esi, 0            ;数组索引
        fldz                     ; 0.0 入栈
        mov ecx,ARRAY_SIZE
    L1: fld    sngArray[esi]     ;将内存操作数加载到ST(0)
        fadd                     ; ST(0) 加 ST(1),出栈
        add esi,TYPE REAL8       ;移至!I 下一个元素
        loop L1
        call WriteFloat          ;显示 ST(0) 中的和数

    平方根之和

    FSQRT 指令对 ST(0) 中的数值求平方根,并将结果送回 ST(0)。下面的代码计算了两个数的平方根之和:

    .data
    valA REAL8 25.0
    valB REAL8 36.0
    .code
    fid valA        ; valA 入栈
    fsqrt           ; ST(0) = sqrt(valA)
    fid valB        ; valB 入栈
    fsqrt           ; ST(0) = sqrt(valB)
    fadd            ; ST (0)+ST(1)

    数组点积

    下面的代码计算了表达式 (airay[0]*airay[l]) + (array[2]*array[3])。该计算有时也被称为点积 (dot product)。

    .data
    array REAL4 6.0, 2.0, 4.5, 3.2

    下表列出了每条指令执行后,FPU 堆栈的情况。输入数据如下:

    指令  FPU堆栈 指令 FPU堆栈
    fld array ST(0):+6.0000000E+000 fmul [array+12] ST(0):+1.4400000E+001
    fmul [array+4] ST(0):+1.2000000E+001   ST(1):+1.2000000E+001
    fld [array+8] ST(0):+4.5000000E+000 fadd ST(0):+2.6400000E+001
      ST(1):+1.2000000E+001      

更多...

加载中...