// 3D Sort Assembler code // Aug 2016 // See http://tropicalcoder.com/3dBubbleSort.htm // Reads colours as bgr void Graphics::Do3DSort(Image *pImage, int limit) { unsigned counter = limit; unsigned width = (unsigned)pImage->imageWidth; unsigned widthMinusOne = width - 1; unsigned widthTimesFour = width * 4; unsigned widthMinusOneTimesFour = widthMinusOne * 4; unsigned widthPlusOneTimesFour = (width + 1) * 4; unsigned height = (unsigned)pImage->imageHeight; unsigned ModVal = (height-1) * width; LPVOID pvBits = pImage->pImageDWordAligned; // Compare RED _asm{ // Pick a pixel at random coordinates x, y where x = {0 thru W - 1)}, y = {0 thru (H - 2)} // x = rand() % width; // y = rand() % (height - 1); // dwPixelA = pImage->getColour(x, y); LOOP_IT: mov eax, counter dec eax mov counter, eax test eax, eax jz DONE call randomMT // Get random offset in eax xor edx,edx mov ecx,ModVal // do mod (height-1) * width (skipping last line)) div ecx // edx has remainder shl edx,2 // * 4 to make it a DWORD offset mov esi,dword ptr [pvBits] add esi,edx mov edi,esi mov ecx, dword ptr [edi] // If amount of red in pixel below (at x, y+1) is greater than red in current pixel, swap pixels // dwPixelB = pImage->getColour(x, y+1); // Second offset can be derived from the first... add esi, widthTimesFour // add width * 4 to make dword offset mov edx, dword ptr [esi] // pixel below (at x, y+1) cmp dl, cl // sort red up jbe NEXT0 mov dword ptr [esi], ecx mov dword ptr [edi], edx } NEXT0: // Compare GREEN _asm{ /* // Pick another pixel at random coordinates x, y where x = {0 thru (W - 2)}, y = {0 thru (H - 2)} x = rand() % (width - 1); y = rand() % (height - 1); dwPixelA = pImage->getColour(x, y); */ GREEN_REPEAT: call randomMT // Get random offset in eax mov ebx,eax // Stored for later xor edx,edx mov ecx,ModVal // do mod (height-1) * width (skipping last line)) div ecx // edx has remainder // We now have in edx the offset to some pixel between 0 and (height-1) * width // We cannot allow a pixel on any given line at (width-1) // x must be from 0 thru (width - 2) // Do if x == (width-1) try again mov esi,edx // store temporarily in ebx // do x % width and compare reaminder to (width-1) mov eax,ebx xor edx,edx mov ecx,width // do mod width div ecx // edx has remainder cmp edx, widthMinusOne jge GREEN_REPEAT // Get the original offset back mov edx,esi // was stored temporarily in esi shl edx,2 // * 4 to make it a DWORD offset mov esi,dword ptr [pvBits] add esi,edx mov edi,esi mov ecx,dword ptr [edi] // If amount of green in pixel to the lower right (at x+1, y+1) is less than green in current pixel, swap pixels // dwPixelB = pImage->getColour(x+1, y+1); add esi, widthPlusOneTimesFour // (width + 1) * 4 to make dword offset mov edx, dword ptr [esi] cmp ch, dh jbe NEXT1 mov dword ptr [esi], ecx mov dword ptr [edi], edx } NEXT1: // Compare BLUE _asm{ // Pick another pixel at random coordinates x, y where x = {1 thru (W - 1)}, y = {0 thru (H - 2)} // x = 1 + (rand() % (width-1)); // y = rand() % (height - 1); // dwPixelA = pImage->getColour(x, y); BLUE_REPEAT: call randomMT // Get random offset in eax mov ebx,eax xor edx,edx mov ecx,ModVal // do mod (height-1) * width (skipping last line)) div ecx // edx has remainder // We now have in edx the offset to some pixel between 0 and (height-1) * width // We cannot allow a pixel on any given line at 0 // x must be from 1 thru (width - 1) // Do if x == 0 try again mov esi,edx // store temporarily in esi mov eax,ebx xor edx,edx // do x % width and compare reaminder to 0 mov ecx,width // do mod width div ecx // edx has remainder cmp edx, 0 je BLUE_REPEAT // Get the original offset back mov edx,esi // was stored temporarily in esi shl edx,2 // * 4 to make it a DWORD offset mov esi,dword ptr [pvBits] add esi,edx mov edi,esi mov ecx,dword ptr [edi] // If amount of blue in pixel to the lower left (at x-1, y+1) is less than blue in current pixel, swap pixels // dwPixelB = pImage->getColour(x-1, y+1); add esi, widthMinusOneTimesFour mov edx, dword ptr [esi] mov ebx, ecx and ecx, 0x00FF0000 mov eax, edx and edx, 0x00FF0000 cmp ecx, edx jbe LOOP_IT mov dword ptr [esi], ebx mov dword ptr [edi], eax jmp LOOP_IT } DONE: counter = 0; }