data segment public
  extrn	buffer:dword		;Pointer to image buffer
  extrn backgnd:dword           ;Pointer to background
  extrn Circle_Start:dataptr	;Definition of circle
  extrn Circle_End:dataptr
data ends

code segment public
assume cs:code,ds:data
.386                            ;386 commands on (32 Bit)
cur_ofs	dw 0									;current offset in destination image
Row_Ofs dw 0                    ;current offset at beginning of row
Circle_Start_cs dw 49*2 dup (0) ;Definition of circle
Circle_End_cs dw 49*2 dup (0)
cur_End dw 0			;current end of circle


root proc pascal                ;extracts root of eax, result in ax
  or eax,eax										;is radicand 0 ?
  je return                     ;then already finished, else:
  push ecx											;save register
  push edx
  xor esi,esi                   ;clear interim results (in esi)
  mov ebx,eax
  xor edx,edx                   ;clear edx
  mov ecx,ebx                   ;store initial value in ecx

iterat:
  cdq
  idiv ebx                      ;divide by Xn
  xor edx,edx                   ;remainder not important
  add eax,ebx                   ;add Xn
  shr eax,1                     ;divide by 2
  sub esi,eax                   ;difference from previous results
  cmp esi,1                     ;less than or equal to 1
  jbe finished                  ;then finished
  mov esi,eax                   ;store results as previous
  mov ebx,eax                   ;record as Xn
  mov eax,ecx                   ;reload initial value for division
  jmp iterat                    ;and to beginning of loop
finished:
  pop edx												;restore register
  pop ecx
return:
  ret                           ;results now in eax
root endp


public magn_asm									;shows magnifying glass effect at coordinates zx/zy
magn_asm proc pascal zx,zy:word
local y_count,x_count:word
push ds												;store ds

  mov bx,cs											;es := cs
  mov es,bx
  lea si,Circle_Start            ;Circle_Start - values to code segment
  lea di,Circle_Start_cs
  mov cx,49                      ;copy 49 values
  rep movsw
  lea si,Circle_End              ;Circle_End - values to code segment
  lea di,Circle_End_cs
  mov cx,49
  rep movsw

  les di,buffer                 ;load destination address: Buffer
  mov ax,zy                     ;add destination coordinates to offset
  imul ax,320
  add ax,zx
  mov cur_ofs,ax                ;destination offset finished
  mov Row_Ofs,ax

  lds si,backgnd                ;source address: background
assume ds:nothing

  xor eax,eax										;clear 32bit register
  xor ebx,ebx
  xor ecx,ecx
  xor edx,edx
  mov y_count,0                 ;y-loop from 48 - 0

next_y:
  mov bx,y_count
  shl bx,1                      ;Array from words
  mov ax,Circle_End_cs[bx]      ;Circle_Start - get value from array
  mov cur_End,ax                ;note for later
  mov bx,Circle_Start_cs[bx]    ;Circle_End - get value from array
  mov x_count,bx								;load x counter
  add cur_ofs,bx                ;in addition, add destination offset

next_x:
  mov ecx,24d										;24= half width of magnifying glass
  movzx eax,y_count             ;load y counter
  sub eax,ecx										;shift center point to middle of magnifying glass
  shl eax,8                     ;for calculating accuracy
  cdq                           ;load edx
  idiv ecx                      ;range of values to -1..1 (-256..256)
  mov ebx,eax                   ;store temporarily in ebx
  movzx eax,x_count             ;the same with the x-counter
  sub eax,24d
  shl eax,8
  cdq
  idiv ecx
  mov ecx,eax                   ;store x in ecx
  mov edx,ebx                   ;and y in edx
  imul eax,eax                  ;square x
  imul ebx,ebx                  ;square y
  add eax,ebx                   ;obtain sum
  call root                     ;and calculate root
  imul eax,24d                  ;multiply roots times half width
  mov edi,eax										;save results for later

  imul eax,edx									;multiply times y-coordinate
  sar eax,16d                   ;offset squaring etc.
  movzx ebx,zy                  ;add destination coordinate
  add eax,ebx
  add eax,24d                   ;shift center
  imul eax,320									;convert to offset
  mov esi,eax                   ;and store in esi

  mov eax,ecx                   ;get x
  imul eax,edi                  ;multiply times root
  sar eax,16d                   ;offset squaring etc.
  movzx ebx,zx                  ;add destination coordinate
  add eax,ebx
  add eax,24d                   ;shift center
  add esi,eax                   ;add to previous offset

  mov di,cur_ofs                ;get current destination offset
  inc cur_ofs                   ;and increment
  movsb                         ;copy point

  inc x_count                   ;increment x counter
  mov ax,cur_End								;already at end ?
  cmp x_count,ax
  jb next_x
  add Row_Ofs,320		;then to next row
  mov ax,Row_Ofs
  mov cur_ofs,ax
  inc y_count                   ;increment y counter
  cmp y_count,48
  jb next_y                    	;if finished,
  pop ds                        ;then finished drawing magnifying glass
  ret
magn_asm endp
code ends
end
