```
Here are some codes taken from "Exagone's Mosaic Tutorial" which I didn't understand.
Please anyone explain to me. My problem is I can't figure out what whole of the algo
is actually doing.
The comments below are made by Exagone himself.
;================================================================================
; --- Loop through all the numbers and draw them one by one ---
xor ebx, ebx
.WHILE ebx<16
mov eax, ebx
inc eax
invoke GetCoordinates, eax
mov dx, ax ; dx = row
shr eax, 16 ; ax = column
and edx, 0ffffh ; make sure that edx = dx
imul edx, edx, 50;} Multipy edx as well as eax with 50
imul eax, 50 ;}
mov TempRect.left, eax
mov TempRect.top, edx
add eax, 50
add edx, 50
mov TempRect.right, eax
mov TempRect.bottom, edx
mov eax, ebx
inc eax
invoke wsprintf, ADDR Buffer, ADDR NumberFormat, eax
invoke DrawText, ImageDC, ADDR Buffer, -1, ADDR TempRect,\
DT_CENTER or DT_SINGLELINE or DT_VCENTER
inc ebx
.ENDW
ret
DrawNumbers endp
;================================================================================
; GetCoordinates
;================================================================================
GetCoordinates proc dwTile:DWORD
mov eax, dwTile
dec eax
cdq
mov ecx, 4
div ecx
;eax=quotient = row
;edx=remainder = column
shl edx, 16
add eax, edx
ret
GetCoordinates endp
;================================================================================
;================================================================================
Well this is the whole algo. Now I will try to explain what I have understood.
MY DOS BASED ASM IS VERY POOR which you'll see in few seconds.
The comments below are made by myself.
;================================================================================
; --- Loop through all the numbers and draw them one by one ---
xor ebx, ebx ;clear EBX
.WHILE ebx<16 ;loop until EBX is less than 16
mov eax, ebx ;since EBX==0 now EAX==0
inc eax ;EAX is now 1
invoke GetCoordinates, eax ;call the subroutine
mov dx, ax ;dx = row ;don't know how
shr eax, 16 ;ax = column ;don't know how
and edx, 0ffffh ;make sure that edx = dx ==>WHY?
;Why EDX must be equal to DX?
imul edx, edx, 50 ;} Multipy edx as well as eax with 50
;Why multiply by 50 and what it is doing.
;I mean why double EDX
imul eax, 50 ;} same question why multiply by 50?
mov TempRect.left, eax ;mov the value in EAX to TempRect.left
mov TempRect.top, edx ;same thing
add eax, 50 ;I know what it is doing
;EAX==EAX+50
;but what it is adding 50 to EAX
add edx, 50 ;same thing here
mov TempRect.right, eax ;moving the value of EAX
mov TempRect.bottom, edx ;moving the value of EDX
mov eax, ebx ;EAX==EAX+EBX==0
inc eax ;EAX==0
invoke wsprintf, ADDR Buffer, ADDR NumberFormat, eax
invoke DrawText, ImageDC, ADDR Buffer, -1, ADDR TempRect,\
DT_CENTER or DT_SINGLELINE or DT_VCENTER
inc ebx ;EBX is now 1
.ENDW ;end the loop is EBX<16
ret ;return
DrawNumbers endp
;================================================================================
; GetCoordinates
;================================================================================
GetCoordinates proc dwTile:DWORD
mov eax, dwTile ;mov dwTile to EAX. If dwTile is moved to EAX
;then what exactly EAX is holding? is it the address.
dec eax ;don't know what is doing?
cdq ;?????
mov ecx, 4 ;ECX==4
div ecx ;divide ECX by EAX and the remainder is in EDX
;eax=quotient = row (how EAX will contain the number of
;row)
;edx=remainder = column (how EDX will contain the number
;of column
shl edx, 16 ;shift EDX by 16. I think it puts zeroes.
add eax, edx ;EAX==EAX+EDX
ret
GetCoordinates endp
;================================================================================
;================================================================================
Can't do better formating than this!
```

```
```

```
I'll explain it here (btw if you didn't know, I'm exagone):
The tiles are counted from 0 to 15 (ebx is the counter). For some functions like GetCoordinates, the tiles are counted from 1 to 16. GetCoordinates takes such a count (0-16) as a parameter and then returns the 'tile coordinates', i.e. the row and column of the tile into the lower and higher words of eax.
``````
Tile numbers (the counter uses)
Table1:
0 1 2 3
4 5 6 7
8 9 10 11
12 13 14 15
Tile numbers (GetCoordinates uses)
Table2:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
Now here are the coordinates in (column, row) format:
Table3:
(0,0) (1,0) (2,0) (3,0)
(0,1) (1,1) (2,1) (3,1)
(0,2) (1,2) (2,2) (3,2)
(0,3) (1,3) (2,3) (3,3)
```

Getcoordinates takes a tile by the numbers in table 2 above, translates it to the numbering in table 1, then converts it to a coordinate like table3. It does this by dividing the tile numbers according to table1 by 4. The remainder of this calculation is the column, the quotient will be the row.
```
GetCoordinates proc dwTile:DWORD
mov eax, dwTile
;eax is now a tile number, counted from 1 to 16 !!!!
dec eax
;eax is decreased by one, to translate the count from 1 to 16, to the count from 0 to 15.
cdq
;cdq extends eax to edx:eax. This is necessairy as the div opcode divides edx:eax, not only eax
mov ecx, 4
div ecx ;divide by 4
;now eax (the quotient) contains the row
;edx (the remainder) contains the column
shl edx, 16
;this shifts the value of edx (the column) to the higher word of edx.
add eax, edx ;the column in the high word of edx is added to the row in the low word in eax
ret
GetCoordinates endp
```

The drawing loop takes the (column, row) coordinates and then determines where the tile should be drawn like this:
tile.leftcoordinate = column * 50
tile.rightcoordinate = column * 50 + 50
tile.topcoordinate = row * 50
tile.bottomcoordinate = row * 50 + 50
The 50 is the size of the tiles, the tiles are 50x50 pixels and logically positioned at coordinates that are multiples of 50 pixels.
O I forgot, this code:
```
mov dx, ax ;dx = row
shr eax, 16 ;ax = column
and edx, 0ffffh ;make sure that edx = dx
```

Before this code, eax contains the column in the high word of eax, and the row in the lower word. mov dx, ax moves the lower word (ax) of eax into the lower word (dx) of edx. Then the high word of eax is shifted into the low word (shr eax, 16) and because the high word of edx is not touched, it can have any value. Therefore, edx is AND-ed with 0ffffh, leaving only the low word in edx (edx=dx). now eax contains the column, and edx contains the row.
I hope you understand it now.
Thomas
This message was edited by Thomas, on 5/3/2001 12:36:35 PM
Thanks Thomas. Now I'll read futher.