はじめに
Delphi10でもまだアセンブラが使えるか試してみました。
複雑なものを書く元気が無いので、学生時代に初めて習ったアルゴリズムである
バブルソートでごまかしてみました。
ソート対象データは data : array [0..DATACOUNT] of integer にセット済みの前提です。
DATACOUNTは定数(const)です。
普通にPascalで記述
// バブルソート
procedure TForm1.bubble;
var i,j,v : integer;
exchange : boolean;
begin
for i := DATACOUNT downto 1 do
begin
exchange := false;
for j := 0 to i-1 do
begin
if data[j] > data[j+1] then
begin
exchange := True;
v := data[j];
data[j] := data[j+1];
data[j+1] := v;
end;
end;
if not exchange then
break;
end;
end;
アセンブラ(かなり怪しい)で記述
// バブルソート(アセンブラ)
procedure TForm1.bubble_asm;
begin
asm
push edi // 変更不可レジスタ退避
push esi // 変更不可レジスタ退避
push ebx // 変更不可レジスタ退避
lea edi,[eax].TForm1.data // data[0]のアドレス
mov edx,DATACOUNT // for i := DATACOUNT
@for1: // 外側ループ処理開始
cmp edx,1 // 外側ループ終了判定
jb @ret // 外側ループ終了判定
mov esi,1 // exchange := false
mov ecx,0 // for j := 0
push edi // data[0]のアドレス保存
@for2: // 内側ループ処理開始
mov eax,[edi] // data[j]
mov ebx,[edi+4] // data[j+1] integer=4byte
cmp eax,ebx // if data[j] > data[j+1]
jbe @noexchange // data[j] <= data[j+1]ならthen以下を実行しない
mov esi,0 // exhcnage = true
mov [edi],ebx // data[j] := data[j+1]
mov [edi+4],eax // data[j+1] := data[j]
@noexchange: // 交換終了(無し)
inc ecx // to i-1
cmp ecx,edx // 内側ループ終了判定
je @for2end // 内側ループ終了判定
add edi,4 // dataへのポインタを1つ進める
jmp @for2 // 内側ループ繰り返し
@for2end: // 内側ループ終了
pop edi // data[0]へ戻す
dec edx // i := i-1
cmp esi,1 // if not exchange then
je @ret // break
jmp @for1 // 外側ループ繰り返し
@ret: // 処理終了
pop ebx // 変更不可レジスタ回復
pop esi // 変更不可レジスタ回復
pop edi // 変更不可レジスタ回復
end;
end;
結果
何とか動きました(汗)
処理時間を測定したところデータ件数10万件で
普通にPascal = 32.7秒
アセンブラ = 18.6秒
ということである程度の高速化にはなっています。
※マシンスペックは別記事を参照してください。
まあ実際に使うことは無いと思いますが…