練習:レジスタの入れ替え
CoddyのAssemblyジャーニー「基礎」セクションの一部 — レッスン 21/45。
時には、2つのレジスタ間で値を入れ替える必要があります。例えば、raxに5が含まれ、rbxに10が含まれている場合、入れ替え後はraxが10になり、rbxが5になる必要があります。
これを1つまたは2つのMOV命令で行うことはできません。一時的なストレージとして3つ目のレジスタが必要です。
直接行えない理由:
; これは動作しません
mov rax, rbx ; これで rax = 10 になりますが、元の 5 は永遠に失われます
mov rbx, rax ; これで rbx も = 10 になります(5 ではありません)正しい方法 — 一時レジスタを使用する:
mov rcx, rax ; ステップ 1: 元の rax を rcx に保存する (rcx = 5)
mov rax, rbx ; ステップ 2: rbx を rax にコピーする (rax = 10)
mov rbx, rcx ; ステップ 3: 保存された値を rcx から rbx にコピーする (rbx = 5)ステップ・バイ・ステップ:
| ステップ | 命令 | rax | rbx | rcx |
|---|---|---|---|---|
| 開始 | (コード実行前) | 5 | 10 | ? |
| 1 | mov rcx, rax | 5 | 10 | 5 |
| 2 | mov rax, rbx | 10 | 10 | 5 |
| 3 | mov rbx, rcx | 10 | 5 | 5 |
これら3つの命令の後、値が入れ替わります。一時レジスタrcxには依然として元の値(5)が含まれていますが、問題ありません。
一時レジスタには、使用していない任意のレジスタを使用できます。
rcx、rdx、r8、または利用可能な任意のレジスタを使用できます。- そのレジスタの元の値が必要ないことを確認してください。
なぜこれが重要なのか:
値の入れ替えは、ソートアルゴリズムやデータ操作において一般的な操作です。これは、MOV命令の順序について慎重に考えることを教えてくれます。
チャレンジ
r8 と r9 の値を入れ替えるためのアセンブリを3行記述してください。
初期値(テストハーネスによって提供されます):
r8は 6 で始まりますr9は 2 で始まります
コード実行後:
r8は 2 になる必要がありますr9は 6 になる必要があります
一時レジスタとして r10 を使用してください。
自分で試してみよう
section .data
msg_r8 db 'r8 = '
msg_r8_len equ $ - msg_r8
msg_r9 db 'r9 = '
msg_r9_len equ $ - msg_r9
newline db 0xa
section .bss
digit resb 1
section .text
global _start
_start:
; 初期値を設定
mov r8, 6
mov r9, 2
%include "solution.asm" ; 受講生の入れ替えコードがここに入ります
; 表示用に値を保存
mov r12, r8
mov r13, r9
; "r8 = " を表示
mov rax, 1
mov rdi, 1
mov rsi, msg_r8
mov rdx, msg_r8_len
syscall
; r8 の値を表示
mov rax, r12
add rax, 48
mov [digit], al
mov rax, 1
mov rdi, 1
mov rsi, digit
mov rdx, 1
syscall
; 改行を表示
mov rax, 1
mov rdi, 1
mov rsi, newline
mov rdx, 1
syscall
; "r9 = " を表示
mov rax, 1
mov rdi, 1
mov rsi, msg_r9
mov rdx, msg_r9_len
syscall
; r9 の値を表示
mov rax, r13
add rax, 48
mov [digit], al
mov rax, 1
mov rdi, 1
mov rsi, digit
mov rdx, 1
syscall
; 改行を表示
mov rax, 1
mov rdi, 1
mov rsi, newline
mov rdx, 1
syscall
; 終了
mov rax, 60
mov rdi, 0
syscallこのレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。