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!
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.
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.
Quote from: MazeGen on August 24, 2006, 02:07:11 PMmov edi, [ebx]CCrc32Dynamic.m_pdwCrc32Table
It's Assume replacement code. Check here for a discussion.
http://www.asmcommunity.net/board/index.php?topic=25199.0
Regards, P1 :8)
So it compiles to something like this, is it correct?
mov edi, [ebp+ebx+x]
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
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)
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.
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.
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.
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.
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
shantanu_gadgil
You can find faster CRC32 samples here:
http://www.asmcommunity.net/board/index.php?topic=7237.0
Regards,
Lingo
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:)
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.
asm code can be smaller and faster: :wink
mov edx, dwBytesRead ; Load dwBytesRead
mov eax, dwCrc32 ; Load Crc32 value
lea edx, [esi + edx] ; Calculate the end of the buffer
mov edi, pTable ; Load the CRC32 table
mov esi, buffer ; Load buffer
crc32loop:
movzx ecx, byte ptr [esi]; Clear the ecx register and Load the current source byte
xor cl, al ; Copy crc value into ecx
shr eax, 8
xor eax, [edi + ecx * 4] ; Get the value out of the table
add esi,1 ; Advance the source pointer
cmp edx, esi ; Have we reached the end of the buffer?
jne crc32loop
ret ;return Crc32 in eax
Regards,
Lingo