练习:交换寄存器
本课属于 Coddy Assembly 学习旅程的“基础知识”单元。第 21 课,共 45 课。
有时你需要交换两个寄存器中的值。例如,如果 rax 中的值是 5,rbx 中的值是 10,那么交换后,rax 中的值应为 10,rbx 中的值应为 5。
你不能只用一条或两条 MOV 指令来完成这件事。你需要第三个寄存器作为临时存储空间。
为什么你不能直接这样做:
; 这样不行
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 |
执行这三条指令后,这些值就交换了。临时寄存器 rcx 仍然保存着原始值(5),但这没关系。
临时寄存器可以是任何你没有使用的寄存器:
- 你可以使用
rcx、rdx、r8或任何可用的寄存器 - 只要确保你不需要该寄存器中的原始值
为什么这很重要:
交换值是排序算法和数据操作中的常见操作。它能让你学会仔细考虑 MOV 指令的顺序。
挑战
写三行汇编代码,交换 r8 和 r9 的值。
初始值(由测试框架提供):
r8的初始值为 6r9的初始值为 2
运行代码后:
r8应为 2r9应为 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 在线编辑器