MOV с операндами разных размеров
Часть раздела Основы путешествия по Assembly на Coddy. Урок 20 из 45.
Вы уже использовали al (8 бит) и rax (64 бита). Но существуют и другие размеры. Разные регистры содержат разное количество данных.
Семейства регистров x86-64:
| Регистр | Размер | bits | Когда использовать |
|---|---|---|---|
rax | 8 байт | 64 bits | Полные числа, адреса, номера syscall |
eax | 4 байта | 32 bits | Младшая половина rax |
ax | 2 байта | 16 bits | Младшая половина eax |
al | 1 байт | 8 bits | Младшая половина ax (bits 0-7) |
ah | 1 байт | 8 bits | Старшая половина ax (bits 8-15) |
Та же закономерность применяется к другим регистрам:
| 64-битный | 32-битный | 16-битный | 8-битный (low) |
|---|---|---|---|
rbx | ebx | bx | bl |
rcx | ecx | cx | cl |
rdx | edx | dx | dl |
rsi | esi | si | sil |
rdi | edi | di | dil |
Почему размер имеет значение:
При перемещении data размеры source и destination должны совпадать. Если они не совпадают, CPU может:
- Скопировать только часть data
- Скопировать дополнительные байты из неизвестной памяти
- Вызвать ошибку
Примеры соответствующих размеров:
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 остаются без измененийКогда вы перемещаете меньшее значение в больший регистр, верхние биты остаются unchanged. Это может привести к неожиданным результатам.
Безопасное правило:
До этого момента в курсе все данные в памяти занимают 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:
; Код студента выполняется первым (загружает из source, сохраняет в destination)
%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Потренируйтесь самостоятельно: Песочница Assembly