;-----------------------------------------------------------------------------
; 9bit fixed point vector math - DOS 16bit realmode (Turbo Pascal version)
; Copyright (c) 1994,95 by J.E. Hoffmann
; All rights reserved
;-----------------------------------------------------------------------------
  TITLE _MATH.ASM


  MODEL SMALL


  IDEAL
  NOJUMPS
  LOCALS @@


  DATASEG


    BitSqrtTbl \
      dw 1,2,2,3,5,7,10,14,20,28,39,55,78,111,157,222,314,443,627,887,1254
      dw 1774,2508,3547,5017,7094,10033,14189,20066,28378,40132,56756

    SinTable \
      DW 00000h, 00006h, 0000Dh, 00013h, 00019h, 0001Fh, 00026h, 0002Ch, 00032h, 00038h, 0003Fh, 00045h, 0004Bh, 00051h, 00058h, 0005Eh
      DW 00064h, 0006Ah, 00070h, 00076h, 0007Ch, 00082h, 00089h, 0008Fh, 00095h, 0009Bh, 000A1h, 000A7h, 000ACh, 000B2h, 000B8h, 000BEh
      DW 000C4h, 000CAh, 000CFh, 000D5h, 000DBh, 000E1h, 000E6h, 000ECh, 000F1h, 000F7h, 000FCh, 00102h, 00107h, 0010Dh, 00112h, 00117h
      DW 0011Ch, 00122h, 00127h, 0012Ch, 00131h, 00136h, 0013Bh, 00140h, 00145h, 0014Ah, 0014Eh, 00153h, 00158h, 0015Ch, 00161h, 00166h
      DW 0016Ah, 0016Eh, 00173h, 00177h, 0017Bh, 00180h, 00184h, 00188h, 0018Ch, 00190h, 00194h, 00197h, 0019Bh, 0019Fh, 001A3h, 001A6h
      DW 001AAh, 001ADh, 001B1h, 001B4h, 001B7h, 001BAh, 001BDh, 001C1h, 001C4h, 001C6h, 001C9h, 001CCh, 001CFh, 001D1h, 001D4h, 001D7h
      DW 001D9h, 001DBh, 001DEh, 001E0h, 001E2h, 001E4h, 001E6h, 001E8h, 001EAh, 001ECh, 001EDh, 001EFh, 001F1h, 001F2h, 001F4h, 001F5h
      DW 001F6h, 001F7h, 001F8h, 001F9h, 001FAh, 001FBh, 001FCh, 001FDh, 001FEh, 001FEh, 001FFh, 001FFh, 001FFh, 00200h, 00200h, 00200h
      DW 00200h


  CODESEG


  PUBLIC VecZero
  PUBLIC Vec
  PUBLIC UnVec
  PUBLIC VecAdd
  PUBLIC VecSub
  PUBLIC VecDot
  PUBLIC VecCross
  PUBLIC VecDistance
  PUBLIC VecLen
  PUBLIC VecScalMul
  PUBLIC VecNormalize

  PUBLIC Zero
  PUBLIC Cross
  PUBLIC Transform
  PUBLIC Rotate
  PUBLIC Create

  PUBLIC VecAdd2D
  PUBLIC VecSub2D


  P386N



;----------------------------------------------------------------------------
; function FixSin(bx) :eax;
;----------------------------------------------------------------------------
  PROC FixSin NEAR
       and    bx,1FFh
       cmp    bx,256
       jge    @@21
       cmp    bx,128
       jng    @@11
       neg    bx
       add    bx,256
  @@11:
       shl    bx,1
       mov    ax,[bx+SinTable]
       cwde
       ret
  @@21:
       sub    bx,256
       cmp    bx,128
       jnge   @@22
       neg    bx
       add    bx,256
  @@22:
       shl    bx,1
       mov    ax,[bx+SinTable]
       neg    ax
       cwde
       ret
  ENDP



;----------------------------------------------------------------------------
; function FixCos(bx) :eax;
;----------------------------------------------------------------------------
  PROC FixCos NEAR
       add    bx,128
       jmp    FixSin
  ENDP



;----------------------------------------------------------------------------
; function FixSqrt(A:eax) :eax
;----------------------------------------------------------------------------
  PROC FixSqrt FAR
       mov    edi,eax
       xor    ecx,ecx
       bsr    ebx,edi
       jz     @@12
       shl    bx,1
       movzx  eax,[bx+BitSqrtTbl]
  @@11:
       xor    edx,edx
       mov    ebx,ecx
       mov    ecx,eax
       mov    eax,edi
       div    ecx
       add    eax,ecx
       shr    eax,1
       cmp    eax,ecx
       je     @@12
       cmp    eax,ebx
       jne    @@11
  @@12:
       mov    eax,ecx
       ret
  ENDP



;ננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננ
; procedure VecZero(var C :T3D);
;ננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננ
  PROC VecZero FAR
       ARG C:DWord = @@return
       enter  0,0
       cld
       les    di,[C]
       xor    eax,eax
       stosd
       stosd
       stosd
       leave
       ret    @@return
  ENDP



;ננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננ
; procedure Vec(vx,vy,vz :LongInt; var C :T3D);
;ננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננ
  PROC Vec FAR
       ARG C:DWord, vz:DWord, vy:DWord, vx:DWord = @@return
       enter  0,0
       cld
       les    di,[C]
       mov    eax,[vx]
       stosd
       mov    eax,[vy]
       stosd
       mov    eax,[vz]
       stosd
       leave
       ret    @@return
  ENDP



;ננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננ
; procedure UnVec(A :T3D; var vx,vy,vz :LongInt);
;ננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננ
  PROC UnVec FAR
       ARG vz:DWord, vy:DWord, vx:DWord, A:DWord = @@return
       enter  0,0
       cld
       push   ds
       lds    si,[A]
       lodsd
       les    di,[vx]
       mov    [es:di],eax
       lodsd
       les    di,[vy]
       mov    [es:di],eax
       lodsd
       les    di,[vz]
       mov    [es:di],eax
       pop    ds
       leave
       ret    @@return
  ENDP



;ננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננ
; procedure VecAdd(A,B :T3D; var C :T3D);
;ננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננ
  PROC VecAdd FAR
       ARG C:DWord, B:DWord, A:DWord = @@return
       enter  0,0
       cld
       push   ds
       lds    si,[A]
       lgs    bx,[B]
       les    di,[C]
       lodsd
       add    eax,[gs:bx]
       stosd
       lodsd
       add    eax,[gs:bx+4]
       stosd
       lodsd
       add    eax,[gs:bx+8]
       stosd
       pop    ds
       leave
       ret    @@return
  ENDP



;ננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננ
; procedure VecSub(A,B :T3D; var C :T3D);
;ננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננ
  PROC VecSub FAR
       ARG C:DWord, B:DWord, A:DWord = @@return
       enter  0,0
       cld
       push   ds
       lds    si,[A]
       lgs    bx,[B]
       les    di,[C]
       lodsd
       sub    eax,[gs:bx]
       stosd
       lodsd
       sub    eax,[gs:bx+4]
       stosd
       lodsd
       sub    eax,[gs:bx+8]
       stosd
       pop    ds
       leave
       ret    @@return
  ENDP



;ננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננ
; function VecDot(A,B :T3D) :LongInt;
;ננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננ
  PROC VecDot FAR
       ARG B:DWord, A:DWord = @@return
       enter  0,0
       push   ds
       lds    si,[A]
       les    di,[B]
       lodsd
       imul   [DWORD PTR es:di+4]
       shrd   eax,edx,9
       mov    ecx,eax
       lodsd
       imul   [DWORD PTR es:di+4]
       shrd   eax,edx,9
       add    ecx,eax
       lodsd
       imul   [DWORD PTR es:di+8]
       shrd   eax,edx,9
       add    ecx,eax
       mov    ax,cx
       rol    ecx,16
       mov    dx,cx
       pop    ds
       leave
       ret    @@return
  ENDP



;ננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננ
; procedure VecCross(A,B :T3D; var C :T3D);
;ננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננ
  PROC VecCross FAR
       ARG C:DWord, B:DWord, A:DWord = @@return
       enter  0,0
       push   ds
       lds    si,[A]
       les    di,[B]
       lgs    bx,[C]
       mov    eax,[si+4]
       imul   [DWORD PTR es:di+8]
       shrd   eax,edx,9
       mov    ecx,eax
       mov    eax,[si+8]
       imul   [DWORD PTR es:di+4]
       shrd   eax,edx,9
       sub    ecx,eax
       mov    [gs:bx],ecx
       mov    eax,[si+8]
       imul   [DWORD PTR es:di]
       shrd   eax,edx,9
       mov    ecx,eax
       mov    eax,[si]
       imul   [DWORD PTR es:di+8]
       shrd   eax,edx,9
       sub    ecx,eax
       mov    [gs:bx+4],ecx
       mov    eax,[si]
       imul   [DWORD PTR es:di+4]
       shrd   eax,edx,9
       mov    ecx,eax
       mov    eax,[si+4]
       imul   [DWORD PTR es:di]
       shrd   eax,edx,9
       sub    ecx,eax
       mov    [gs:bx+8],ecx
       pop    ds
       leave
       ret    @@return
  ENDP



;ננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננ
; function VecDistance(A :T3D) :LongInt;
;ננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננ
  PROC VecDistance FAR
       ARG A:DWord = @@return
       enter  0,0
       push   ds
       lds    si,[A]
       lodsd
       or     eax,eax
       jns    @@11
       neg    eax
  @@11:
       mul    eax
       shrd   eax,edx,9
       mov    ecx,eax
       lodsd
       or     eax,eax
       jns    @@12
       neg    eax
  @@12:
       mul    eax
       shrd   eax,edx,9
       add    ecx,eax
       lodsd
       or     eax,eax
       jns    @@13
       neg    eax
  @@13:
       mul    eax
       shrd   eax,edx,9
       add    ecx,eax
       mov    ax,cx
       rol    ecx,16
       mov    dx,cx
       pop    ds
       leave
       ret    @@return
  ENDP



;ננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננ
; function VecLen(A :T3D) :LongInt;
;ננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננ
  PROC VecLen FAR
       ARG A:DWord = @@return
       enter  0,0
       push   ds
       lds    si,[A]
       lodsd
       or     eax,eax
       jns    @@11
       neg    eax
  @@11:
       mul    eax
       shrd   eax,edx,9
       mov    ecx,eax
       lodsd
       or     eax,eax
       jns    @@12
       neg    eax
  @@12:
       mul    eax
       shrd   eax,edx,9
       add    ecx,eax
       lodsd
       or     eax,eax
       jns    @@13
       neg    eax
  @@13:
       mul    eax
       shrd   eax,edx,9
       add    eax,ecx
       shl    eax,1
       call   FixSqrt
       shl    eax,4
       rol    eax,16
       mov    dx,ax
       rol    eax,16
       pop    ds
       leave
       ret    @@return
  ENDP



;ננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננ
; procedure VecScalMul(k :LongInt; A :T3D; var C :T3D);
;ננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננ
  PROC VecScalMul FAR
       ARG C:DWord, A:DWord, k:DWord = @@return
       enter  0,0
       push   ds
       lds    si,[A]
       les    di,[C]
       lodsd
       imul   [k]
       shrd   eax,edx,9
       stosd
       lodsd
       imul   [k]
       shrd   eax,edx,9
       stosd
       lodsd
       imul   [k]
       shrd   eax,edx,9
       stosd
       pop    ds
       leave
       ret    @@return
  ENDP



;ננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננ
; procedure VecNormalize(var C :T3D);
;ננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננ
  PROC VecNormalize FAR
       ARG C:DWord = @@return
       enter  0,0
       push   [C]
       call   VecLen
       mov    ecx,eax
       les    di,[C]
       mov    eax,[es:di]
       cdq
       shld   edx,eax,9
       shl    eax,9
       idiv   ecx
       stosd
       mov    eax,[es:di]
       cdq
       shld   edx,eax,9
       shl    eax,9
       idiv   ecx
       stosd
       mov    eax,[es:di]
       cdq
       shld   edx,eax,9
       shl    eax,9
       idiv   ecx
       stosd
       leave
       ret    @@return
  ENDP



;ננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננ
; procedure Zero(var C :TMatrix);
;ננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננ
  PROC Zero FAR
       ARG C :DWord = @@return
       enter  0,0
       les    di,[C]
       xor    eax,eax
       mov    cx,(4*4*4)/4
       repne  stosd
       leave
       ret    @@return
  ENDP



;ננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננ
; procedure Cross(var A,B :TMatrix; var C :TMatrix);
;ננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננ
  PROC Cross FAR
       ARG C:DWord, B:DWord, A:DWord = @@return
       LOCAL i:Word, j :Word = @@local
       enter  @@local,0
       mov    [i],3
  @@11:
       mov    [j],3
  @@21:
       mov    bx,[j]
       shl    bx,2
       les    di,[B]
       add    di,bx
       mov    bx,[i]
       shl    bx,4
       lfs    si,[A]
       add    si,bx
       xor    ebx,ebx
       mov    cx,4
  @@31:
       mov    eax,[fs:si]
       imul   [DWORD PTR es:di]
       shrd   eax,edx,9
       add    ebx,eax
       add    si,4
       add    di,16
       loop   @@31
       les    di,[C]
       mov    ax,[j]
       shl    ax,2
       add    di,ax
       mov    ax,[i]
       shl    ax,4
       add    di,ax
       mov    [es:di],ebx
       dec    [j]
       jns    @@21
       dec    [i]
       jns    @@11
       leave
       ret    @@return
  ENDP



;ננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננ
; procedure Transform(A :T3D; M :TMatrix; var C :T3D);
;ננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננ
  PROC Transform FAR
       ARG C:DWord, M:DWord, A:DWord = @@return
       enter  0,0
       lfs    si,[A]
       lgs    bx,[M]
       les    di,[C]
       mov    cx,3
  @@11:
       push   cx
       mov    eax,[fs:si]
       imul   [DWORD PTR gs:bx]
       shrd   eax,edx,9
       mov    ecx,eax
       mov    eax,[fs:si+4]
       imul   [DWORD PTR gs:bx+4]
       shrd   eax,edx,9
       add    ecx,eax
       mov    eax,[fs:si+8]
       imul   [DWORD PTR gs:bx+8]
       shrd   eax,edx,9
       add    ecx,eax
       add    ecx,[DWORD PTR gs:bx+12]
       mov    [es:di],ecx
       add    di,4
       add    bx,16
       pop    cx
       loop   @@11
       leave
       ret    @@return
  ENDP



;ננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננ
; procedure Rotate(rx,ry,rz :Integer; var R :TMatrix);
;ננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננ
  PROC Rotate FAR
       ARG R:DWord, rz:Word, ry:Word, rx:Word = @@return
       LOCAL SinX:DWord,SinY:DWord,SinZ:DWord,CosX:DWord,CosY:DWord,CosZ:DWord,A:DWord,B:DWord = @@local
       enter  @@local,0
       les    di,[R]
       push   di
       mov    cx,(4*4*4)/4
       xor    eax,eax
       repne  stosd
       pop    di

       mov    bx,[rx]
       call   FixSin
       mov    [SinX],eax
       mov    bx,[rx]
       call   FixCos
       mov    [CosX],eax
       mov    bx,[ry]
       call   FixSin
       mov    [SinY],eax
       mov    bx,[ry]
       call   FixCos
       mov    [CosY],eax
       mov    bx,[rz]
       call   FixSin
       mov    [SinZ],eax
       mov    bx,[rz]
       call   FixCos
       mov    [CosZ],eax

       imul   [SinY]
       shrd   eax,edx,9
       mov    [A],eax
       mov    eax,[SinZ]
       imul   [SinY]
       shrd   eax,edx,9
       mov    [B],eax
       mov    eax,[CosZ]
       imul   [CosY]
       shrd   eax,edx,9
       mov    [es:di],eax
       mov    eax,[A]
       imul   [SinX]
       shrd   eax,edx,9
       mov    ebx,eax
       mov    eax,[SinZ]
       imul   [CosX]
       shrd   eax,edx,9
       sub    ebx,eax
       mov    [es:di+4],ebx
       mov    eax,[A]
       imul   [CosX]
       shrd   eax,edx,9
       mov    ebx,eax
       mov    eax,[SinZ]
       imul   [SinX]
       shrd   eax,edx,9
       add    eax,ebx
       mov    [es:di+8],eax
       mov    eax,[SinZ]
       imul   [CosY]
       shrd   eax,edx,9
       mov    [es:di+16],eax
       mov    eax,[B]
       imul   [SinX]
       shrd   eax,edx,9
       mov    ebx,eax
       mov    eax,[CosZ]
       imul   [CosX]
       shrd   eax,edx,9
       add    eax,ebx
       mov    [es:di+20],eax
       mov    eax,[B]
       imul   [CosX]
       shrd   eax,edx,9
       mov    ebx,eax
       mov    eax,[CosZ]
       imul   [SinX]
       shrd   eax,edx,9
       sub    ebx,eax
       mov    [es:di+24],ebx
       mov    eax,[SinY]
       neg    eax
       mov    [es:di+32],eax
       mov    eax,[CosY]
       imul   [SinX]
       shrd   eax,edx,9
       mov    [es:di+36],eax
       mov    eax,[CosY]
       imul   [CosX]
       shrd   eax,edx,9
       mov    [es:di+40],eax
       mov    eax,200h
       mov    [es:di+60],eax
       leave
       ret    @@return
  ENDP



;ננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננ
; procedure Create(tx,ty,tz, sx,sy,sz :LongInt; rx,ry,rz :Integer; var M :TMatrix);
;ננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננ
  PROC Create FAR
       ARG M:DWord, rz:Word, ry:Word, rx:Word, sz:DWord, sy:DWord, sx:DWord, tz:DWord, ty:DWord, tx:DWord = @@return
       LOCAL SinX:DWord,SinY:DWord,SinZ:DWord,CosX:DWord,CosY:DWord,CosZ:DWord,A:DWord,B:DWord = @@local
       enter  @@local,0
       les    di,[M]
       push   di
       mov    cx,(4*4*4)/4
       xor    eax,eax
       repne  stosd
       pop    di

       mov    bx,[rx]
       call   FixSin
       mov    [SinX],eax
       mov    bx,[rx]
       call   FixCos
       mov    [CosX],eax
       mov    bx,[ry]
       call   FixSin
       mov    [SinY],eax
       mov    bx,[ry]
       call   FixCos
       mov    [CosY],eax
       mov    bx,[rz]
       call   FixSin
       mov    [SinZ],eax
       mov    bx,[rz]
       call   FixCos
       mov    [CosZ],eax

       imul   [SinY]
       shrd   eax,edx,9
       mov    [A],eax
       mov    eax,[SinZ]
       imul   [SinY]
       shrd   eax,edx,9
       mov    [B],eax
       mov    eax,[CosZ]
       imul   [CosY]
       shrd   eax,edx,9
       imul   [sx]
       shrd   eax,edx,9
       mov    [es:di],eax
       mov    eax,[SinZ]
       imul   [CosX]
       shrd   eax,edx,9
       mov    ebx,eax
       mov    eax,[A]
       imul   [SinX]
       shrd   eax,edx,9
       sub    eax,ebx
       imul   [sx]
       shrd   eax,edx,9
       mov    [es:di+4],eax
       mov    eax,[A]
       imul   [CosX]
       shrd   eax,edx,9
       mov    ebx,eax
       mov    eax,[SinZ]
       imul   [SinX]
       shrd   eax,edx,9
       add    eax,ebx
       imul   [sx]
       shrd   eax,edx,9
       mov    [es:di+8],eax
       mov    eax,[SinZ]
       imul   [CosY]
       shrd   eax,edx,9
       imul   [sy]
       shrd   eax,edx,9
       mov    [es:di+16],eax
       mov    eax,[B]
       imul   [SinX]
       shrd   eax,edx,9
       mov    ebx,eax
       mov    eax,[CosZ]
       imul   [CosX]
       shrd   eax,edx,9
       add    eax,ebx
       imul   [sy]
       shrd   eax,edx,9
       mov    [es:di+20],eax
       mov    eax,[CosZ]
       imul   [SinX]
       shrd   eax,edx,9
       mov    ebx,eax
       mov    eax,[B]
       imul   [CosX]
       shrd   eax,edx,9
       sub    eax,ebx
       imul   [sy]
       shrd   eax,edx,9
       mov    [es:di+24],eax
       mov    eax,[SinY]
       neg    eax
       imul   [sz]
       shrd   eax,edx,9
       mov    [es:di+32],eax
       mov    eax,[CosY]
       imul   [SinX]
       shrd   eax,edx,9
       imul   [sz]
       shrd   eax,edx,9
       mov    [es:di+36],eax
       mov    eax,[CosY]
       imul   [CosX]
       shrd   eax,edx,9
       imul   [sz]
       shrd   eax,edx,9
       mov    [es:di+40],eax
       mov    eax,[tx]
       imul   [sx]
       shrd   eax,edx,9
       mov    [es:di+12],eax
       mov    eax,[ty]
       imul   [sy]
       shrd   eax,edx,9
       mov    [es:di+28],eax
       mov    eax,[tz]
       imul   [sz]
       shrd   eax,edx,9
       mov    [es:di+44],eax
       mov    eax,200h
       mov    [es:di+60],eax
       leave
       ret    @@return
  ENDP



;ננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננ
; procedure VecAdd2D(A,B :T2D; var C :T2D);
;ננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננ
  PROC VecAdd2D FAR
       ARG C:DWord, B:DWord, A:DWord = @@return
       enter  0,0
       les    di,[C]
       mov    ax,[WORD PTR A]
       add    ax,[WORD PTR B]
       stosw
       mov    ax,[WORD PTR A+2]
       add    ax,[WORD PTR B+2]
       stosw
       leave
       ret    @@return
  ENDP



;ננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננ
; procedure VecSub2D(A,B :T2D; var C :T2D);
;ננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננננ
  PROC VecSub2D FAR
       ARG C:DWord, B:DWord, A:DWord = @@return
       enter  0,0
       les    di,[C]
       mov    ax,[WORD PTR A]
       sub    ax,[WORD PTR B]
       stosw
       mov    ax,[WORD PTR A+2]
       sub    ax,[WORD PTR B+2]
       stosw
       leave
       ret    @@return
  ENDP
  END

