porting Crc32Dynamic from Visual Studio.net to 64bit Visual Studio 2005

Started by sidewalk_bends, August 23, 2006, 11:47:03 PM

Previous topic - Next topic

sidewalk_bends

I am trying to port Crc32Dynamic from Visual Studio.net to Visual Studio 2005, which does not allow inline asm. I've decided to compile a seperate .asm file that contains my function, however I am having trouble with passing a table generated by a function using C++, to my new .asm file. How would I go about fixing the two lines of code in bold.


old inline code:

            // Register use:
            //      eax - CRC32 value
            //      ebx - a lot of things
            //      ecx - CRC32 value
            //      edx - address of end of buffer
            //      esi - address of start of buffer
            //      edi - CRC32 table
            __asm
            {
               // Save the esi and edi registers
               push esi
               push edi

               mov eax, dwCrc32         // Load the pointer to dwCrc32
               mov ecx, [eax]            // Dereference the pointer to load dwCrc32

               mov ebx, this            // Load the CRC32 table
               mov edi, [ebx]CCrc32Dynamic.m_pdwCrc32Table


               lea esi, buffer            // Load buffer
               mov ebx, dwBytesRead      // Load dwBytesRead
               lea edx, [esi + ebx]      // Calculate the end of the buffer

            crc32loop:
               xor eax, eax            // Clear the eax register
               mov bl, byte ptr [esi]      // Load the current source byte
               
               mov al, cl               // Copy crc value into eax
               inc esi                  // Advance the source pointer

               xor al, bl               // Create the index into the CRC32 table
               shr ecx, 8

               mov ebx, [edi + eax * 4]   // Get the value out of the table
               xor ecx, ebx            // xor with the current byte

               cmp edx, esi            // Have we reached the end of the buffer?
               jne crc32loop

               // Restore the edi and esi registers
               pop edi
               pop esi

               mov eax, dwCrc32         // Load the pointer to dwCrc32
               mov [eax], ecx            // Write the result
            }



this is defined as this type in Visual Studio: const CCrc32Dynamic *const this. It contains a list of polynomials generated by some code in C++ in Crc32Dynamic.cpp

I've used this to pass values to my other variables but am unsure about the lines in bold: crc32dynamic PROC dwCrc32:DWORD, buffer:BYTE, dwBytesRead:DWORD, m_pdwCrc32Table:DWORD



Thanks for any help!

MazeGen

Hi sidewalk_bends,

welcome on board.

I can help you with the port. The only thing I don't know is where this is located under x64 conventions. If you know more about it, let me know. I try to ask my friend in the meantime.

MazeGen

OK, I know where this, but I'm unsure about

mov edi, [ebx]CCrc32Dynamic.m_pdwCrc32Table

Could you provide a disassembly of that function? I believe VC++ has some switch to produce generated assembly code.

[EDIT] Or just show me how looks this instruction in a debugger.

P1


MazeGen

So it compiles to something like this, is it correct?

mov edi, [ebp+ebx+x]

sidewalk_bends

Hi,

Thanks for the replies and the welcome.

I actually have not written assembly code since I first learned how to program at school and so revisting it is kind of interesting. I actually figured out the problem with: mov edi, [ebx]CCrc32Dynamic.m_pdwCrc32Table although I'm not entirely sure what that line really does. I'll have to read up on the suggestion about ASSUME at some point. I just declared CCrc32Dynamic.m_pdwCrc32Table as CCrc32Dynamic.m_pdwCrc32Table:DWORD Looking back at the C++ code, I figured out it was some variable of type DWORD defined by a class.

Now I just need to find out how to deal with this.

Also, I'm assuming since I am trying to port to a 64bit compiler, I will have to add r to the register names? I think I read that somewhere on some AMD documentation.

By the way, this Crc32dynamic was some freeware code that we use in our software. It can be found free here but you need to sign up http://www.codeproject.com/cpp/crc32.asp?df=100 We just use the dynamic version. Let me know if I should post the whole thing here. It's one .cpp file and two .h files

P1

Quote from: sidewalk_bends on August 24, 2006, 05:40:50 PMNow I just need to find out how to deal with this.
Normally, out of this context.  It's a COM pointer.  No pun intended.   :wink

But it's not being used as a COM pointer ( No de-referencing is taking place to the vtable or calling any functions.), so it's an every day base table pointer.  To which you can use structured access to work through the table.

So do you know the table format?

Regards,  P1  :8)

sidewalk_bends

Actually I made a mistake, the problem with the second line in bold is still a problem. It has to do with syntax. So I assume I'll have to read up on ASSUME much sooner than I thought.

P1

Quote from: sidewalk_bends on August 24, 2006, 06:08:49 PMActually I made a mistake, the problem with the second line in bold is still a problem. It has to do with syntax. So I assume I'll have to read up on ASSUME much sooner than I thought.
Duh ( for me ), I could have been coding by now !!!   :eek

I use the MASM assume syntax when coding.  So go for it.

Regards,  P1  :8)

PS:  CCrc32Dynamic is declare with the structure type, so start there.

Vortex

ASSUME EDX : PTR IMAGE_EXPORT_DIRECTORY
MOV  EBX, [EDX.IMAGE_EXPORT_DIRECTORY].AddressOfNames

Translated to:
MOV  EBX, IMAGE_EXPORT_DIRECTORY.AddressOfNames[EDX]


The translation works for both of Masm and Poasm.

MazeGen

Oh, I was confused because I thought the inline code is inside separated function.

Well guys, anyone knows how to translate this class to MASM structure?


class CCrc32Dynamic
{
public:
CCrc32Dynamic();
virtual ~CCrc32Dynamic();

void Init(void);
void Free(void);

DWORD StringCrc32(LPCTSTR szString, DWORD &dwCrc32) const;
DWORD FileCrc32Streams(LPCTSTR szFilename, DWORD &dwCrc32) const;
DWORD FileCrc32Win32(LPCTSTR szFilename, DWORD &dwCrc32) const;
DWORD FileCrc32Filemap(LPCTSTR szFilename, DWORD &dwCrc32) const;
DWORD FileCrc32Assembly(LPCTSTR szFilename, DWORD &dwCrc32) const;

protected:
static bool GetFileSizeQW(const HANDLE hFile, QWORD &qwSize);
inline void CalcCrc32(const BYTE byte, DWORD &dwCrc32) const;

DWORD *m_pdwCrc32Table;
};


All what I know is that PTR m_pdwCrc32Table is at offset 4. Or hardcoding the offset would be enough?

I can't recompile the project and look at the generated output since I don't have VC++ 6.

Shantanu Gadgil

If you are looking for a CRC32 calculation routine in ASM, maybe this might help?
http://www.masm32.com/board/index.php?topic=5589.0

Regards,
Shantanu
To ret is human, to jmp divine!


drizz

no no no, why are you complicating things with classes and c++?
i mean theres no need to translate class nor anything like that... :snooty:

sidewalk_bends, if you want my advice, just replace __asm {} block with this line:
for (int i=0;i<dwBytesRead;i++) CalcCrc32(buffer[i],dwCrc32);

OR if you really want to link asm, liten carefully, i shall say this only once
   
dont fool yourself that asm will outperform compiler generated code, not that asm at least.. :)

change __asm {} block with this line:
dwCrc32=DoCrc32(dwCrc32,buffer,dwBytesRead,(PBYTE)m_pdwCrc32Table);
add the function definition somwhere (e.g. at start of file)
extern "C" __stdcall DoCrc32(DWORD dwCrc,PBYTE buff,DWORD dwBR,PBYTE pTable);
changed a bit inline asm; put it in a .asm file:
.686
.model flat,stdcall
option casemap:none
.code
; Save the ebx,esi and edi registers
DoCrc32 proc uses esi edi ebx dwCrc32:DWORD,buffer:DWORD,dwBytesRead:DWORD,pTable:DWORD

; Register use:
; eax - CRC32 value
; ebx - a lot of things
; ecx - CRC32 value
; edx - address of end of buffer
; esi - address of start of buffer
; edi - CRC32 table
mov ecx, dwCrc32 ; Load the pointer to dwCrc32

mov edi, pTable ; Load the CRC32 table

mov esi, buffer ; Load buffer
mov ebx, dwBytesRead ; Load dwBytesRead
lea edx, [esi + ebx] ; Calculate the end of the buffer

crc32loop:
xor eax, eax ; Clear the eax register
mov bl, byte ptr [esi] ; Load the current source byte

mov al, cl ; Copy crc value into eax
inc esi ; Advance the source pointer

xor al, bl ; Create the index into the CRC32 table
shr ecx, 8

mov ebx, [edi + eax * 4] ; Get the value out of the table
xor ecx, ebx ; xor with the current byte

cmp edx, esi ; Have we reached the end of the buffer?
jne crc32loop

mov eax, ecx ; return Crc32
ret
DoCrc32 endp

end


now just link the compiled asm object file (i hope no need for explanation here...)
and translate the 32bit asm to 64bit if required..


edit: small fix with typecasting (god how i hate that  :dazzled:)
The truth cannot be learned ... it can only be recognized.

sidewalk_bends

Thank you everyone for your suggestions and replies. I decided to go with that for loop that drizz suggested rather than toy around with masm. Our other alternative was to use an entirely different algorithm called MD5 which completely avoids masm.