|
ぱんかずです。
頭の体操になりました。少々、長いことをお許しください。
#また、なかなかフォローできません。ご了承ください。
> 最近、性能が気になって仕方がない状態になってしまいまして、文字列の比較をア
>センブリ語で書いてしまいました。
>
> 文字列の比較といっても、例えば「0123」と「123」を同一視するタイプで、しか
>も大文字/小文字を区別しないタイプのややこしい文字列比較です。
>
> せっかく作ったのでここに書き込んでしまいます。(charはすべてunsignedです)
>
> 間違ってたらご指摘を。
>
間違ってるかまでは見れてませんが、少々コメントさせてください。
movzx は便利な命令ですが、パイプライン制御などの関係で、遅延が発生する
要因となる場合があり、単純命令の組み合わせで書いた方が良いというような
記述を見たことがあります。(Pentiumの仕様書だったかな?)
それ以下の命令もDWORD比較よりもBYTE比較で済むはずですので、わざわざ
DWORDに拡張しなくても良いのではないでしょうか?
#命令はどれも1クロックですが、定数の分命令長が大きくなります。
あと、cでreturnされるならば、nに戻り値を設定しておく必要があるのでは
ないでしょうか?
>static int _stdcall CompareStringSuper( char* psz1, char* psz2 ) {
>#if 0
> int n;
> for(;;) {
> if( *psz1 >= '0' && *psz1 <= '9'
> && *psz2 >= '0' && *psz2 <= '9' ) {
> int cchNumber1 = 0, cchNumber2 = 0;
> while( *psz1 == '0' ) {
> psz1 ++;
> }
> while( *psz1 >= '0' && *psz1 <= '9' ) {
> cchNumber1 ++;
> *psz1 ++;
(1) 引数の値がかわりませんか?
> }
> while( *psz2 == '0' ) {
> psz2 ++;
> }
> n = cchNumber1 - cchNumber2;
(2) cchNumber2は0のままではありませんか?
アセンブラの方は、カウントしていますが…
> if( n != 0 ) {
> break;
> }
> n = memcmp( psz1 - cchNumber1, psz2 - cchNumber1, cchNumber1 );
> if( n != 0 ) {
> break;
> }
> } else {
> char ch1 = *psz1;
> if( ch1 >= 'a' && ch1 < 'z' ) {
(3) 'z'が範囲から漏れませんか?
> ch1 = ch1 - 'a' + 'A';
> }
> char ch2 = *psz2;
> if( ch2 >= 'a' && ch2 < 'z' ) {
(3)'
> ch2 = ch2 - 'a' + 'A';
> }
> n = ch1 - ch2;
> if( n != 0 ) {
> break;
> }
> if( ch1 == '\0' ) {
> return 0;
> }
> if( (ch1 >= 0x81 && ch1 <= 0x9F) || ch1 >= 0xE0 ) {
> psz1 ++;
> psz2 ++;
> n = *psz1 - *psz2;
> if( n != 0 ) {
> break;
> }
> }
> psz1 ++;
> psz2 ++;
> }
> }
> return n;
>#endif
> _asm {
> mov esi, psz1
> mov edi, psz2
>Loop1:
> movzx eax,[esi]
> cmp eax,'9'
> ja NotNumber
> cmp eax,'0'
> jb NotNumber
> movzx ebx,[edi]
> cmp ebx,'9'
> ja NotNumber2
> cmp ebx,'0'
> jb NotNumber2
> // 数字同士の場合
> dec esi // psz1側での'0'をスキップ
>Loop3:
> inc esi
> mov al,[esi]
> cmp al,'0'
> je Loop3
> // psz1側での数字の桁数を数える --> eaxに入れる
> mov eax,-1
> dec esi
>Loop4:
> inc esi
> inc eax
> mov bl,[esi]
> cmp bl,'0'
> jb Skip4
> cmp bl,'9'
> jbe Loop4
>Skip4:
> dec edi // psz2側での'0'をスキップ
>Loop5:
> inc edi
> mov bl,[edi]
> cmp bl,'0'
> je Loop5
> // psz2側での数字の桁数を数える --> ecxに入れる
> mov ecx,-1
> dec edi
>Loop6:
> inc edi
> inc ecx
> mov bl,[edi]
> cmp bl,'0'
> jb Skip6
> cmp bl,'9'
> jbe Loop6
>Skip6:
> sub eax,ecx
> jnz Exit // 桁数が一致しない時はそこで終わり
>
> neg ecx // ecx = - ecx
> sub eax,eax
>Loop7:
> movzx eax,[esi+ecx]
> movzx ebx,[edi+ecx]
> sub eax,ebx
> jnz Exit
> inc ecx
> jnz Loop7
> jmp Loop1
>
>NotNumber:
> movzx ebx,[edi]
>NotNumber2:
> sub eax,ebx
> jz BigSkip1
> add eax,ebx
> cmp eax,'z'
> ja Skip10
> cmp eax,'a'
> jb Skip10
> add eax,'A'-'a'
>Skip10:
> cmp ebx,'z'
> ja Skip11
> cmp ebx,'a'
> jb Skip11
> add ebx,'A'-'a'
>Skip11:
> sub eax,ebx
> jnz Exit
>BigSkip1:
> or ebx,ebx
> jz Exit // 全部一致している場合。eaxも0になっているはず。
> cmp ebx,81h
> jb NotKanji
> cmp ebx,0E0h
> jae Kanji
> cmp ebx,9Fh
> jbe Kanji
>
>NotKanji:
> inc esi
> inc edi
> jmp Loop1
>
>Kanji:
> inc esi
> inc edi
> movzx eax,[esi]
> movzx ebx,[edi]
> inc esi
> inc edi
> sub eax,ebx
> jz Loop1
> // jmp Exit
>
>Exit:
> }
> // return eax
>}
以下、私が書き換えたものを送ります。
#VCおよびアセンブラを持ち合わせていないため、動作確認できていません。
-------------------------------------------------------------------
_asm {
mov esi, psz1
mov edi, psz2
Loop1:
mov bl, byte ptr [edi]
cmp bl, '9'
ja NotNumber2
cmp bl, '0'
jb NotNumber2
mov al, byte ptr [esi]
cmp al, '9'
ja NotNumber
cmp al, '0'
jb NotNumber
jnz L1 // '0'以外ならば、桁数処理
xchg esi, edi
rep scasb // '0'をSKIP
xchg esi, edi
L1: // psz1側での数字の桁数を数える --> edxに
入れる
xor edx, edx
Loop4:
mov al, byte ptr [esi]
cmp al, '0'
jb Skip4
cmp al, '9'
ja Skip4
inc esi
inc edx
jmp Loop4
Skip4:
cmp bl, '0'
jnz L2 // '0'以外ならば、桁数処理
mov al, bl // al = '0'
rep scasb // '0'をSKIP
L2:
xor ecx, ecx
Loop6:
mov bl, byte ptr [edi]
cmp bl, '0'
jb Skip6
cmp bl, '9'
ja Skip6
inc edi
inc ecx
jmp Loop6
Skip6:
mov eax, edx
sub eax, ecx
jnz Exit // 桁数が一致しない時はそこで終わり
neg ecx // ecx = - ecx
xor eax, eax
xor ebx, ebx
Loop7:
mov al, byte ptr [esi+ecx]
mov bl, byte ptr [edi+ecx]
sub al, bl
jnz Exit
inc ecx
jnz Loop7
jmp Loop1
NotNumber:
mov bl, byte ptr [edi]
NotNumber2:
xor ebx, ebx
xor eax, eax
sub al, bl
jz BigSkip1
add al, bl
cmp al, 'z'
ja Skip10
cmp al, 'a'
jb Skip10
add al, 'A'-'a'
Skip10:
cmp bl, 'z'
ja Skip11
cmp bl, 'a'
jb Skip11
add bl, 'A'-'a'
Skip11:
sub al, bl
jnz Exit
BigSkip1:
or bl, bl
jz Exit // 全部一致している場合。eaxも0になっている
はず。
cmp bl, 81h
jb NotKanji
cmp bl, 0E0h
jae Kanji
cmp bl, 9Fh
jbe Kanji
NotKanji:
inc esi
inc edi
jmp Loop1
Kanji:
inc esi
inc edi
mov al, byte ptr [esi]
mov bl, byte ptr [edi]
inc esi
inc edi
sub eax, ebx
jz Loop1
// jmp Exit
Exit:
mov dword ptr [n], eax // cのreturn文でnから値を取得す
るため
}
// return eax
|
|