Практика: обмен значениями регистров
Часть раздела Основы путешествия по Assembly на Coddy — урок 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В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Основы
1Машина
Что такое CPUПамятьРегистры против памятиКак работают инструкцииПаттерн двух файловАрхитектура x86-643Первая инструкция — MOV
Что такое MOV?MOV: непосредственные значенияMOV: из регистра в регистрMOV: из памяти в регистрMOV: из регистра в памятьLEA — загрузка адресаMOV с операндами разных размеровПрактика: обмен значениями регистровИтоги: испытание MOV