MOV с операндами разных размеров
Часть раздела Основы путешествия по Assembly на Coddy — урок 20 из 45.
Вы уже использовали al (8 бит) и rax (64 бита). Но существуют и другие размеры. Разные регистры хранят разный объем данных.
Семейства регистров x86-64:
| Регистр | Размер | Биты | Когда использовать |
|---|---|---|---|
rax | 8 байт | 64 бита | Целые числа, адреса, номера системных вызовов |
eax | 4 байта | 32 бита | Младшая половина rax |
ax | 2 байта | 16 бит | Младшая половина eax |
al | 1 байт | 8 бит | Младшая половина ax (биты 0-7) |
ah | 1 байт | 8 бит | Старшая половина ax (биты 8-15) |
Тот же шаблон применим к другим регистрам:
| 64-бит | 32-бита | 16-бит | 8-бит (младший) |
|---|---|---|---|
rbx | ebx | bx | bl |
rcx | ecx | cx | cl |
rdx | edx | dx | dl |
rsi | esi | si | sil |
rdi | edi | di | dil |
Почему размер имеет значение:
При перемещении данных размеры источника и назначения должны совпадать. Если они не совпадают, процессор может:
- Скопировать только часть данных
- Скопировать лишние байты из неизвестной области памяти
- Вызвать ошибку
Примеры соответствия размеров:
mov rax, 1000 ; 64-бит в 64-бит (ок)
mov eax, 1000 ; 32-бит в 32-бит (ок)
mov ax, 1000 ; 16-бит в 16-бит (ок)
mov al, 5 ; 8-бит в 8-бит (ок)Что происходит при несовпадении размеров:
mov rax, 0x123456789ABC ; 64-битное значение
mov al, 0xFF ; al получает 0xFF, остальные биты rax остаются без измененийКогда вы перемещаете меньшее значение в регистр большего размера, старшие биты остаются неизменными. Это может привести к неожиданным результатам.
Безопасное правило:
В этом курсе на данный момент все данные в памяти занимают 1 байт. Вот почему вы используете al (а не rax).
При перемещении данных размер регистра должен соответствовать размеру памяти:
- 1 байт памяти → используйте
al,bl,clи т. д. - 8 байт памяти → используйте
rax,rbx,rcxи т. д.
Вы узнаете о различных размерах памяти в Главе 3.
Задание
У вас уже созданы следующие адреса данных:
source— содержит 1-байтовое значение (5)destination— пустое место (1 байт)
Напишите две строки на ассемблере, чтобы:
- Загрузить значение из
sourceвal - Сохранить значение из
alвdestination
Попробуйте сами
section .data
msg db 'destination = '
msg_len equ $ - msg
section .bss
digit resb 1
section .text
global _start
_start:
; Код студента выполняется первым (загружает из источника, сохраняет в место назначения)
%include "solution.asm"
; Загрузить сохраненное значение из destination
mov al, [destination]
; Сохранить его
mov r12, rax
; Вывести "destination = "
mov rax, 1
mov rdi, 1
mov rsi, msg
mov rdx, msg_len
syscall
; Вывести значение
mov rax, r12
add rax, 48
mov [digit], al
mov rax, 1
mov rdi, 1
mov rsi, digit
mov rdx, 1
syscall
; Выход
mov rax, 60
mov rdi, 0
syscallВ этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Основы
1Машина
Что такое CPUПамятьРегистры против памятиКак работают инструкцииПаттерн двух файловАрхитектура x86-643Первая инструкция — MOV
Что такое MOV?MOV: непосредственные значенияMOV: из регистра в регистрMOV: из памяти в регистрMOV: из регистра в памятьLEA — загрузка адресаMOV с операндами разных размеровПрактика: обмен значениями регистровИтоги: испытание MOV