fc2ブログ

Speeeeed Ver1.51

置換えリストエディタにバグがあったので修正です。
長い文字列を登録しても保存時に256バイト以降が勝手に削除されてました。
あと、ちょっとしたGUIのバグ修正も。

どうやらリストコントロールに問題がある感じ。
リストコントロールにLVM_GETITEMTEXTを投げ戻る値は通常ならLVITEM構造体のcchTextMaxで指定したサイズより文字列が大きい場合は、cchTextMax-1だけコピーし最後に\0を付加し戻り値としてcchTextMax-1が返りますが、2バイト文字が含まれる場合cchTextMaxコピーしcchTextMaxを返します。
そのため、MFCの実装でもし戻り値が用意したバッファ-1のサイズならサイズを確保しなおし再取得する訳ですが、一つ大きい値が返ってくるのでそこで処理が終わってしまい後ろが切れてしまいます。
# ただしUnicode版(W版)では発生しないと思われます。

この問題結構影響大きいですね。
Clipyも同様に後ろが切れるバグ抱えてます。
とは言えClipyにおいてNT系はW版のAPI使ってるので9x系でしか起きない問題ですが。

他に最近アセンブラで色々遊んでるので文字列検索のルーチンをアセンブラ化して更に高速化させようかと思ったけどVC++の最適化ってかなり凄いので下手に弄ったら余計遅くなるような気もしたのでこれはヤメ。
サイズの最適化なら上手くできてるか簡単に把握できますが速度の最適化は環境によっても変わるから確かめにくいですし。


では以下更新点の詳細です。

続きを読む

スポンサーサイト



lltoa(インラインアセンブラ版)

64ビット符号付き整数(LONGLONG)を文字列に変換する関数。
無駄にアセンブラで実装。
必要に駆られて作ったけど要らなくなってしまい消すのも勿体無いのでメモ。
速度よりサイズ重視。まだ改良の余地はありげ。
# バッファに反転コピー辺りはストリング命令使えばもっと良くなるはず

肝は負数は反転して正数にしてしまうのと64bit整数の割り算で商が32bitを超える場合の対処法で、最初に上位32bitを割っておいてその商を別に保存し、余りを上位32bitに設定しなおして再度割ってやるとオーバーフローせずに32bitに収まり、別に保存した上位32bitと計算結果の商の下位32bitで64bitの商が弾き出せます。

というわけで以下コード。

void lltoa(LONGLONG value, char *string)
{
char tmp[20];
_asm {
; edi データ保存
; esi 割る数(10)
; ecx:ebx value
// 絶対値取得
lea edi, tmp
mov esi, 10
mov ecx, dword ptr[value+4]
mov ebx, dword ptr[value]
or ecx, ecx
jge LTA1
mov eax, ecx
mov edx, ebx
neg eax
neg edx
sbb eax, 0
mov ecx, eax
mov ebx, edx
mov eax, string
mov [eax], '-'
inc string
// 商余Get
LTA1: mov eax, ecx
xor edx, edx
div esi
mov ecx, eax ; 商上位32bit
mov eax, ebx
div esi
mov ebx, eax ; 商下位32bit
add edx, '0' ; 余
mov [edi], dl
inc edi
test ecx,ecx
jne LTA1
test ebx,ebx
jne LTA1
// バッファに反転コピー
lea ebx, tmp
mov esi, string
LTA2: dec edi
mov al, [edi]
mov [esi], al
inc esi
cmp edi, ebx
jne LTA2
mov [esi], 0
}
}

新規記事の投稿


月別アーカイブ
カテゴリー
リンク
ブログ内検索
RSSフィード