有一个 Pascal 程序,最初不是我写的。我把它翻译成C#。在程序的一部分中,对文件校验和进行了非常特殊的计算。校验和以格式存储在数据库中,bigint
校验和计算函数如下所示:
function GetCheckSum(FileName: string): DWORD;
var
F: file of DWORD;
P: Pointer;
Fsize: DWORD;
Buffer: array[0..500] of DWORD;
begin
FileMode := 0;
AssignFile(F, FileName);
Reset(F);
Seek(F, FileSize(F) div 2);
Fsize := FileSize(F) - 1 - FilePos(F);
if Fsize > 500 then
Fsize := 500;
BlockRead(F, Buffer, Fsize);
Close(F);
P := @Buffer;
asm
XOR eax, eax
XOR ecx, ecx
mov edi, P
@again:
add eax, [edi + 4 * ecx]
inc ecx
cmp ecx, Fsize
jl @again
mov @result, eax
end;
end;
告诉我汇编器中发生了什么,以及这种构造在 C# 中的样子?
使用了以下内容:
private long GetCheckSum(string FilePath)
{
byte[] FBytes = File.ReadAllBytes(FilePath);
int FSize = FBytes.Length / 2;
int FToRead = FSize + 500 > FBytes.Length ? FBytes.Length : FSize + 500;
long FSum = 0;
for (int i = FSize; i < FToRead; i++)
{
FSum += FBytes[i];
}
return FSum;
}
在我看来,结果是一样的。如我错了请纠正我。
只是 32 位无符号数的总和(如果发生溢出,取模 2^32)。
该文件以二进制形式读取,对文件后半部分的数字进行求和(感谢
Seek
),它们的数量不超过 500。因此。对于 8000 字节(2000 个数字)的文件大小,将读取 1000 到 1499 的数字。对于 800 字节(200 个数字)的文件大小,将读取 100 到 199 的数字。类似 c 的伪代码中的解释
是这样的吗:
它似乎返回了你需要的东西。
BitConverter.ToUInt32
将数组中的 4 个字节从指定位置转换为 32 位无符号数。该函数本身GetCheckSum
从文件中读取一系列字节。找出文件的中间位置,并从它开始,最多运行 2000 个元素(如果有的话),步长为 4。也就是说,实际上最多 500 个步长。使用函数BitConverter.ToUInt32
获取无符号数的总和并返回。