pcjs/pubs/x86/ops/AAD/AAD.ASM
2017-09-12 11:28:18 -07:00

201 lines
9.3 KiB
NASM

.386p
;-----------------------------------------------------------------------------
;
; AAD.ASM Copyright (c) 1991, 1995-Present, Robert Collins
;
; You have my permission to copy and distribute this software for
; non-commercial purposes. Any commercial use of this software or
; source code is allowed, so long as the appropriate copyright
; attributions (to me) are intact, *AND* my email address is properly
; displayed.
;
; Basically, give me credit, where credit is due, and show my email
; address.
;
;-----------------------------------------------------------------------------
;
; Robert R. Collins email: rcollins@x86.org
;
;-----------------------------------------------------------------------------
.model small
.code
.286
;-----------------------------------------------------------------------------
; Interrupt vector segment
;-----------------------------------------------------------------------------
ABS0 segment at 0
org 0*4
Orig_INT0 label word
ABS0 ends
;-----------------------------------------------------------------------------
; Local stack frame variable(s)
;-----------------------------------------------------------------------------
INT0 equ [bp-4]
;-----------------------------------------------------------------------------
; Instruction macro definition
;-----------------------------------------------------------------------------
AADI MACRO VALUE
db 0d5h,VALUE
ENDM
;-----------------------------------------------------------------------------
TEST_AAD proc near ; Test AAD IMMED08 instruction functionality.
;-----------------------------------------------------------------------------
; AAD:
; {
; AL = AH*IMMED08 + AL
; AH = 0
; CF = AL[b7] Overflow?
; OF = AL[b7] set, but not overflow? or AL[b7] overflow, but not set?
; AF = AL[b3] overflow, or AL[b3] borrow?
; SF = AL[b7]=1?
; ZF = AL==0?
; PF = Even/Odd parity
; }
; Input: None
; Output: BX = Bit mask of results (3FFF if all tests passed)
; [b13] = 1, NS flag test passed
; [b12] = 1, SF flag test passed
; [b11] = 1, NZ flag test passed
; [b10] = 1, ZF flag test passed
; [b09] = 1, PO flag test passed
; [b08] = 1, PE flag test passed
; [b07] = 1, AF (test 2) flag test passed
; [b06] = 1, AF (test 1) flag test passed
; [b05] = 1, NA flag test passed
; [b04] = 1, OF (test 2) flag test passed
; [b03] = 1, NO flag test passed
; [b02] = 1, OF (test 1) flag test passed
; [b01] = 1, CY flag test passed
; [b00] = 1, NC flag test passed
; Register(s) modified: AX, BX, CX
;-----------------------------------------------------------------------------
xor bx,bx ; clear result flags
xor cx,cx
;-----------------------------------------------------------------------------
; Test Carry Flag set. According to Intel, CF is undefined after AAD, but
; should be set according to the results. Since this is an arithmatic
; operation, CF should be set according to the results. Let's find out!
;-----------------------------------------------------------------------------
mov ax,3300h ; set AH=51, AL=0 and perform 51*5.
AADI 5 ; result should not produce a CF
jc @F ; oops
or bl,1 ; set NC passed
@@: mov ax,3301h ; set AH=51, AL=1 and perform
AADI 5 ; (55*5)+1 should set CF
jnc @F ; oops, didn't work
or bl,2 ; set CF passed
;-----------------------------------------------------------------------------
; Test Overflow Flag set. There are two ways the OF can be set:
; 1) If AL[b7] is set, but doesn't overflow into CF;
; 2) If AL[b7] overflows, but doesn't get set.
;-----------------------------------------------------------------------------
; 1) If AL[b7] is set, but doesn't overflow into CF;
;-----------------------------------------------------------------------------
mov ax,2a02h ; perform (42*3)+2 = 128, should set
AADI 3 ; OF.
jno @F ; oops, didn't work
or bl,4 ; set OF passed
@@: mov ax,8080h ; perform (128*2)+128, should not set
AADI 2 ; OF because it sets CF, & AL[b7]
jo @F ; oops, didn't work
or bl,8 ; set NO passed
;-----------------------------------------------------------------------------
; 2) If AL[b7] overflows, but doesn't get set.
;-----------------------------------------------------------------------------
@@: mov ax,8080h ; perform (128*2)+128, should not set
AADI 1 ; OF because it sets CF, & AL[b7]
jno @F ; oops, didn't work
or bl,10h
;-----------------------------------------------------------------------------
; Test Auxiliary carry Flag (AF) set. AF is set in two ways:
; 1) If there is a carry out of bit3;
; 2) If there is a borrow out of bit3.
;-----------------------------------------------------------------------------
@@: mov ax,2200h ; perform (34*5)+0, should not set
AADI 5 ; AM because no carry from bit3
lahf ; get flags
test ah,10h ; AF set?
jnz @F ; yes, must have been a mistake
or bl,20h ; set NA flag passed
;-----------------------------------------------------------------------------
; 1) If there is a carry out of bit3;
;-----------------------------------------------------------------------------
@@: mov ax,2208h ; perform (34*5)+8, should set AF
AADI 5 ; because a bit3 will carry
lahf ; get flags
test ah,10h ; AF set?
jz @F ; nope, oops
or bl,40h ; set AF flag passed
;-----------------------------------------------------------------------------
; 2) If there is a borrow out of bit3.
; (This may not be an accurate test of borrowing out of bit 3, because
; this test adds a -8 to the result of the multplication. In other
; words, the addition algorithm is still used, not the subtraction
; algorithm -- if they are even different in the first place.)
;-----------------------------------------------------------------------------
@@: mov ax,22f8h ; perform (34*5)-8, should set AF
AADI 5 ; because a bit3 will borrow
lahf ; get flags
test ah,10h ; AF set?
jz @F ; nope, oops
or bl,80h ; set AF flag passed
;-----------------------------------------------------------------------------
; Test EVEN and ODD parity by generating results in the low byte that
; contain even and odd parity respectively.
;-----------------------------------------------------------------------------
@@: mov ax,0a00h ; 10*17+0 which is EVEN parity
AADI 11h
jpo @F ; didn't generate even parity
or bh,1 ; set even parity flag passed
@@: mov ax,0a01h ; 10*17+1 which is ODD parity
AADI 11h
jpe @F ; didn't generate odd parity
or bh,2 ; set odd parity flag passed
;-----------------------------------------------------------------------------
; Test ZERO FLAG by generating results that produce a zero, and non-zero.
;-----------------------------------------------------------------------------
@@: mov ax,0880h ; 8*16+128 will generate a zero result
AADI 10h ; This should force ZF=1
jnz @F ; didn't work as expected
or bh,4
@@: mov ax,0881h ; 8*16+129 will be non-zero
AADI 10h ; This should force ZF=0,
jz @F ; didn't work as expected
or bh,8
;-----------------------------------------------------------------------------
; Test Sign Flag by generating results whose highest bit is on.
; I'll try and do this in a manner that doesn't set OF.
;-----------------------------------------------------------------------------
mov ax,80c0h ; (128*128)+192 will generate SF
AADI 80h ; without generating OF.
jns @F ; oops
or bh,10h ; set SF flag passed
@@: mov ax,8040h ;
AADI 80h
js @F
or bh,20h
@@: ret
Test_AAD endp
end