为什么我的 asm 校验和宏的 Dart 实现不起作用?
Why my Dart implementation of an asm checksum macro does not work?
我正在尝试为 Dart 语言实现一个用 masm32 编写的 32 位校验和宏。
这是我的理解:校验和函数将字符串作为输入,returns 校验和为 4 字节整数。
但我没有得到相同的结果。
请问有人看到我的错误吗?
; ecx : length of String variable
; esi : pointer to String variable
; eax : 'return' value of calculated checksum
CHECKSUM32_MACRO MACRO
LOCAL Checksum32Loop, Checksum32Done
xor eax,eax
cmp ecx,4
jb Checksum32Done
align 16
Checksum32Loop:
mov ebx,dword ptr [esi]
add eax,ebx
shl ebx,1
adc ebx,1
xor eax,ebx
add esi,4
sub ecx,4
jz Checksum32Done
cmp ecx,4
jae Checksum32Loop
mov edx,4
sub edx,ecx
sub esi,edx
mov ecx,4
jmp Checksum32Loop
Checksum32Done:
ENDM
int checksum(String src){
int i = src.length-1;
int res = 0;
do{
int c = src.codeUnitAt(i);
res += c;
String cBits = c.toRadixString(2);
int bitFort = int.parse(cBits[0]);
int transform = c << 1;
transform = transform + 1 + bitFort;
res = res ^ transform;
i--;
}while(i>=0);
return res;
}
我按照提示修改了代码,假设一个ASCII字符串总是4的倍数,有时间看懂问题了。
不过还是不行。
String deComp = File(CHEMIN_FICHIER_DECOMP).readAsStringSync();
List<int> encoded = [];
for (int i =0; i<deComp.length; i++){
List<int> cUtf8 = utf8.encode(deComp[i]);
encoded.addAll(cUtf8);
}
print(checksum_stack(encoded));
_______
int checksum_stack(List<int> src){
int i = 0;
int res = 0;
do{
int c = fusion(src.sublist(i, i+4));
res += c;
String cBits = c.toRadixString(2).padLeft(8, '0');
int bitFort = int.parse(cBits[0]);
int transform = c << 1;
transform = transform + 1 +bitFort;
res = res ^ transform;
i+=4;
}while(i < src.length-4);
return res;
}
int fusion(List<int> str){
if (str.length != 4) {
throw "need multiple of 4!";
}
String hexStr = "";
str.forEach((c) {
hexStr += c.toRadixString(16).padLeft(2, '0');
});
return int.parse(hexStr,radix: 16);
}
校验和算法的转录有误。
以下是我的做法:
import 'dart:convert';
import 'dart:math';
import 'dart:typed_data';
int checksum(String string, {Encoding encoder = utf8, Endian endian = Endian.little})
{
final ByteData bytes = ByteData.sublistView(Uint8List.fromList(encoder.encode(string)));
int checksum = 0;
if (bytes.lengthInBytes >= 4)
{
for (int i = 0; i < bytes.lengthInBytes; i += 4)
{
int chunk = bytes.getUint32(min(i + 4, bytes.lengthInBytes) - 4, endian);
checksum = (checksum + chunk) ^ ((chunk << 1) + 1 + (chunk >> 31));
}
}
return checksum & 0xffffffff;
}
你完全错过了:
- 代码使用 DWORD(32 位整数)。
- 少于 4 个字节的字符串的校验和为零。
- 代码通过读取最后四个字节(必然与前一个 DWORD 重叠)来处理长度不是四的倍数的字符串。
这是评论的程序集:
CHECKSUM32_MACRO MACRO
LOCAL Checksum32Loop, Checksum32Done
xor eax,eax ;Checksum = 0
cmp ecx,4
jb Checksum32Done ;If len < 4 Then Return
align 16
Checksum32Loop:
mov ebx,dword ptr [esi] ;c = DWORD from string (**FOUR** bytes)
add eax,ebx ;Checksum += c
shl ebx,1 ;CF = c[31], c = c << 1
adc ebx,1 ;c += (1 + CF)
xor eax,ebx ;Checksum ^= c
add esi,4 ;Point to next DWORD
sub ecx,4 ;Len -= 4
jz Checksum32Done ;If Len == 0 Then Return
cmp ecx,4
jae Checksum32Loop ;If Len >= 4 Then Cycle back
mov edx,4
sub edx,ecx ;edx = 4 - Len (left, so it's 4 - Len % 4 in absolute terms)
sub esi,edx ;Point to last DWORD (Len-4 in absolute terms, go back 4-Len in relative terms)
mov ecx,4 ;Set Len=4 to cycle one more time
jmp Checksum32Loop
Checksum32Done:
ENDM
另请注意,将数字转换为字符串以提取数字或位通常是一种不好的做法。使用 >>
移位运算符,最后使用 AND。
我正在尝试为 Dart 语言实现一个用 masm32 编写的 32 位校验和宏。 这是我的理解:校验和函数将字符串作为输入,returns 校验和为 4 字节整数。 但我没有得到相同的结果。 请问有人看到我的错误吗?
; ecx : length of String variable
; esi : pointer to String variable
; eax : 'return' value of calculated checksum
CHECKSUM32_MACRO MACRO
LOCAL Checksum32Loop, Checksum32Done
xor eax,eax
cmp ecx,4
jb Checksum32Done
align 16
Checksum32Loop:
mov ebx,dword ptr [esi]
add eax,ebx
shl ebx,1
adc ebx,1
xor eax,ebx
add esi,4
sub ecx,4
jz Checksum32Done
cmp ecx,4
jae Checksum32Loop
mov edx,4
sub edx,ecx
sub esi,edx
mov ecx,4
jmp Checksum32Loop
Checksum32Done:
ENDM
int checksum(String src){
int i = src.length-1;
int res = 0;
do{
int c = src.codeUnitAt(i);
res += c;
String cBits = c.toRadixString(2);
int bitFort = int.parse(cBits[0]);
int transform = c << 1;
transform = transform + 1 + bitFort;
res = res ^ transform;
i--;
}while(i>=0);
return res;
}
我按照提示修改了代码,假设一个ASCII字符串总是4的倍数,有时间看懂问题了。 不过还是不行。
String deComp = File(CHEMIN_FICHIER_DECOMP).readAsStringSync();
List<int> encoded = [];
for (int i =0; i<deComp.length; i++){
List<int> cUtf8 = utf8.encode(deComp[i]);
encoded.addAll(cUtf8);
}
print(checksum_stack(encoded));
_______
int checksum_stack(List<int> src){
int i = 0;
int res = 0;
do{
int c = fusion(src.sublist(i, i+4));
res += c;
String cBits = c.toRadixString(2).padLeft(8, '0');
int bitFort = int.parse(cBits[0]);
int transform = c << 1;
transform = transform + 1 +bitFort;
res = res ^ transform;
i+=4;
}while(i < src.length-4);
return res;
}
int fusion(List<int> str){
if (str.length != 4) {
throw "need multiple of 4!";
}
String hexStr = "";
str.forEach((c) {
hexStr += c.toRadixString(16).padLeft(2, '0');
});
return int.parse(hexStr,radix: 16);
}
校验和算法的转录有误。
以下是我的做法:
import 'dart:convert';
import 'dart:math';
import 'dart:typed_data';
int checksum(String string, {Encoding encoder = utf8, Endian endian = Endian.little})
{
final ByteData bytes = ByteData.sublistView(Uint8List.fromList(encoder.encode(string)));
int checksum = 0;
if (bytes.lengthInBytes >= 4)
{
for (int i = 0; i < bytes.lengthInBytes; i += 4)
{
int chunk = bytes.getUint32(min(i + 4, bytes.lengthInBytes) - 4, endian);
checksum = (checksum + chunk) ^ ((chunk << 1) + 1 + (chunk >> 31));
}
}
return checksum & 0xffffffff;
}
你完全错过了:
- 代码使用 DWORD(32 位整数)。
- 少于 4 个字节的字符串的校验和为零。
- 代码通过读取最后四个字节(必然与前一个 DWORD 重叠)来处理长度不是四的倍数的字符串。
这是评论的程序集:
CHECKSUM32_MACRO MACRO
LOCAL Checksum32Loop, Checksum32Done
xor eax,eax ;Checksum = 0
cmp ecx,4
jb Checksum32Done ;If len < 4 Then Return
align 16
Checksum32Loop:
mov ebx,dword ptr [esi] ;c = DWORD from string (**FOUR** bytes)
add eax,ebx ;Checksum += c
shl ebx,1 ;CF = c[31], c = c << 1
adc ebx,1 ;c += (1 + CF)
xor eax,ebx ;Checksum ^= c
add esi,4 ;Point to next DWORD
sub ecx,4 ;Len -= 4
jz Checksum32Done ;If Len == 0 Then Return
cmp ecx,4
jae Checksum32Loop ;If Len >= 4 Then Cycle back
mov edx,4
sub edx,ecx ;edx = 4 - Len (left, so it's 4 - Len % 4 in absolute terms)
sub esi,edx ;Point to last DWORD (Len-4 in absolute terms, go back 4-Len in relative terms)
mov ecx,4 ;Set Len=4 to cycle one more time
jmp Checksum32Loop
Checksum32Done:
ENDM
另请注意,将数字转换为字符串以提取数字或位通常是一种不好的做法。使用 >>
移位运算符,最后使用 AND。