64ビットLinuxで実行されるNASMで選択ソートの配列を実装しようとしています。
配列は次のように宣言されます。
section .bss
strbuf resb 10
small resb 1 ; current minimum value
ソートアルゴリズム自体は非常に単純ですが、使用可能なレジスタの数と、イミディエート(つまりブラケット)を交換できないという2つの点で制限されていると感じています。
並べ替えられていない配列の境界、そのインデックス、現在の最小値の場所、およびそのインデックスを追跡する必要があります。これはすでに4つのレジスタです。また、2つのループカウンターを追跡する必要があります。1つはソートされていない配列境界を表す外側のループ用で、もう1つは各パスの反復用(つまり内側のループ)です。これはさらに2つ、合計6つのレジスタです。
mov [var1], [var2]
2つの要素を交換する必要があるときはいつでも、一時的なプレースホルダーとしてレジスターを使用する必要があるなど、イミディエートを相互に移動することはできません。これは、どのレジスタがどの情報を保持しているかを追跡するという点で、すぐに扱いにくくなります。
以下はこれまでの私の試みです。これは、セグメンテーション違反を引き起こす機能しないコードであることに注意してください。しかし、おそらくあなたは私がやろうとしていることを理解し、私のアプローチがどこで間違っているのかを指摘することができます。
.IFや.ELSEを提供するマクロなど、構成を単純化するマクロは使用したくありません。
; ====== Sorting begins here ======
sorting:
mov edi, strbuf ; outer loop pointer
mov esi, strbuf ; inner loop pointer
mov eax, 0 ; inner loop counter
mov ebx, 0 ; outer loop counter
innerloop:
; store the value of first element in [small]
mov edx, [esi]
mov [small], edx
; compare the current small value with the value pointed by esi
mov edx, [esi]
cmp [small], edx
jg new_small
inc esi
inc eax
cmp eax, 9
jle innerloop
cmp eax, 9
jg innerloop_done
new_small:
mov [small], edx ; save the new small value
mov ecx, esi ; save its index in ecx
inc esi
inc eax
cmp eax, 9
jle innerloop
innerloop_done:
; When the inner loop is completed...
; First, do the swap
push rax
mov eax, [edi]
mov edx, [small]
mov [ecx], edx
pop rax
inc edi ; move the outer loop pointer forward
inc esi ; move the inner loop pointer forward
inc ebx ; increment the outer loop counter (the unsorted array becomes smaller)
inc eax ; increment the inner loop counter (same reason as above)
cmp ebx, 9
jle innerloop
; ====== Sorting ends here ======