練習:レジスタの入れ替え
CoddyのAssemblyジャーニー「基礎」セクションの一部。レッスン 21/45。
2つのレジスタ間で値をSwapする必要がある場合があります。たとえば、raxに5が含まれ、rbxに10が含まれている場合、Swap後はraxが10、rbxが5になるはずです。
これを 1 つまたは 2 つの MOV 命令だけで行うことはできません。一時的な記憶領域として 3 つ目のレジスターが必要です。
直接実行できない理由:
; これは動作しません
mov rax, rbx ; これで rax = 10 ですが、元の 5 は永遠に失われました
mov rbx, rax ; これで rbx も = 10 です(5 ではありません)正しい方法:temporary registerをusingする:
mov rcx, rax ; ステップ1: 元のraxをrcxに保存する (rcx = 5)
mov rax, rbx ; ステップ2: rbxをraxにコピーする (rax = 10)
mov rbx, rcx ; ステップ3: rcxから保存した値をrbxにコピーする (rbx = 5)Stepごとに:
| Step | 命令 | 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)がまだ含まれていますが、それで問題ありません。
一時レジスタには、using していない任意のレジスタを使用できます:
rcx、rdx、r8、または利用可能な任意のレジスタを使用できます- そのレジスタのoriginal の値が必要ないことを確認してください
これが重要な理由:
値のSwapは、ソートアルゴリズムやデータ操作でよく行われる処理です。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このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
基礎のすべてのレッスン
自分で練習してみよう: Assemblyプレイグラウンド