作ったプログラムのデバッグをするとき、アセンブラが読めると便利です。
少しだけ高速化したい時
ObjectPascalで表現出来ない数式がある時
インラインアセンブラは強力な武器になります。そんな目的に実はDelphiやFreePascalは便利です。デバッガーもサポートしてくれます。単体のアセンブラで試すのは色々と事前準備から必要ですからね。
アセンブラの表記や機械語そのものの知識は検索すれば得られるので検索に必要な用語を学ぶ程度のお話となります。
逆アセンブラを見る
1 見たいソースのブレークポイントを設定します。
⇒行番号表示の左側をマウスクリックするか F5
2 実行した後そこでブレークして表示されないなら
表示→デバッグ表示→アセンブラ
試しに
pascalには shr はあるのに asrが無いので 除算で代用したので
Int32((Int64(x) * Int64(y)) div $1000000)のアセンブラ結果
movslq -0x8(%rbp),%rax ;//32bit>64bit符号拡張
movslq -0x10(%rbp),%rdx ;
imul %rdx,%rax ;//64bitx64bit->rAX+(rDX shl 64)
mov %rax,%rdx ;
sar $0x3f,%rdx ;//MSBで63bitを埋める
and $0xffffff,%rdx ;//結果、負数の時だけ $ffffff
add %rdx,%rax ;
sar $0x18,%rax ;//24bitの算術シフト
この $ffffffとのANDしてANDは何をしてるかというと丸めの調整です。負数の時の剰余分を+方に丸めてくれているのです。でも私には不要なんです。
インラインアセンブラを使ってみる
Int32((Int64(x) * Int64(y)) sar 24) の結果が欲しいのに不要な丸めが入るのは困ります。そこで
function mpySAR24(x, y: Integer): Integer;
begin
asm
MOVSLQ x,%RAX ;
MOVSLQ y,%RDX ;
IMUL %RDX,%RAX ;
SAR $24,%RAX ;//$は16進数ではなく 即値の事
end ['rAX']; //結果がRAXだと教えてる
end; //整数型の返り値は基本的にRAX
MASM表記とは違う
LazarusmのFreePascalはLinux系ですからx86のころから伝統的にアセンブラの表記がMASMとは異なります。
・引数の向きが反対 a,b とあれば MASMでは 結果はaですが 逆になっています
・表記方法の違い レジスタ,即値,間接メモリ参照の表現方法が違います。
レジスタを表現するには "%"文字をレジスタ名の前に付けます
即値(immediate)には$を数値の前に付けます(16進数を示すには 0x)
間接メモリ参照では 数値(レジスタ)や 数値(レジスタ1,レジスタ2,倍数)
・コメントはPascal式 //より右か {この範囲} か (* この範囲 *)
MASMを先に学んだ方は注意して下さい