Search code examples
assemblyx86masmirvine32fpu

Masking divide by 0 exception assembly masm


TITLE Unmasking an Exception    (Exceptions.asm)

; This program shows how to mask (set) and unmask (clear) the divide by zero
; exception flag.

INCLUDE Irvine32.inc

.data
ctrlWord WORD ?
val1 DWORD 1
val2 REAL8 0.0

.code
main PROC
finit       ; initialize FPU (divide by zero is masked)

; By unmasking, we enable the divide by zero exception.

fstcw   ctrlWord                ; get the control word
and ctrlWord,1111111111111011b  ; unmask Divide by 0
fldcw   ctrlWord                ; load it back into FPU

fild    val1
fdiv    val2                        ; divide by zero
fst val2

exit
main ENDP
END main

Hi everyone, i am very new to masm and am taking myself through some online projects i can find and am having trouble with this one, as you can see it unmasks the divide by 0 exception but how can i edit this to mask that same exception? If you can please explain and be as detailed as possible that will help out a ton!


Solution

  • fstcw   ctrlWord                ; get the control word
    and ctrlWord,1111111111111011b  ; unmask Divide by 0
    fldcw   ctrlWord                ; load it back into FPU
    

    The mask bit (ZM) for the zero-divide exception is bit 2 of the FPU control word. It would improve readability if you didn't write a long masking value like "1111111111111011b".
    Since bit 2 is represented by the value 4, a more readable way to clear this bit is:

    and ctrlWord, not(4)
    

    Some people will even prefer to write and ctrlWord, not(1<<2) since this one still retains reference to the bit number (2 in this case).

    Now when adopting this improvement, masking the zero-divide exception becomes a matter of changing the and into an or and dropping the not operator.

    and ctrlWord, not(4)    ---->    or ctrlWord, 4
    

    As an alternative you can also clear or set a bit using btr and bts instructions:

    and ctrlWord, not(4)    ---->    btr ctrlWord, 2          ;Clears bit 2
    or  ctrlWord, 4         ---->    bts ctrlWord, 2          ;Sets bit 2