LoginSignup
12
3

More than 3 years have passed since last update.

Delphi10 まだアセンブラが使えるか試してみた

Last updated at Posted at 2020-04-29

はじめに

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秒
ということである程度の高速化にはなっています。
※マシンスペックは別記事を参照してください。
まあ実際に使うことは無いと思いますが…

12
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
3