.global main
.data
arr: .short 1, 0xEA, 0x2, 0x3, 0b1010
.text
main:
lea (arr), %rbx
movb 3(%rbx),%al #1
movw arr+3, %ax #2
когда я пробую этот код, al
получает значение 0x0
, однако ax
получает значение 0x200
можешь сказать почему так? какая разница между №1 и №2?
Разница должна быть очевидна, первый загружает только al
(младшие 8 бит), а второй загружает ax
(16 бит). Обратите внимание, что al
равно нулю в обоих случаях, как и ожидалось. 3(%rbx)
и arr+3
делают одно и то же, важно то, что movb
против movw
. Кроме того, в ассемблере используется байтовая адресация, а .short
составляет 2 байта, поэтому arr+3
является старшим байтом 0xEA
(который равен нулю) и адресация смещена.
У нас были предыдущие вопросы и ответы о несоосных нагрузках и о том, какие данные вы получаете, некоторые с хорошими ответами. Однако я не могу найти его прямо сейчас и не уверен, что есть дубликат, который также явно покрывает очевидную разницу в загрузке 1 и 2 байта.
Поскольку x86 — это архитектура с прямым порядком байтов, данные в arr
выглядят так:
arr+0 +1 +2 +3 +4 +5 +6 +7 +8 +9
0x01 0x00 0xEA 0x00 0x02 0x00 0x03 0x00 0x0A 0x00
#1 считывает данные в al
. al
— это однобайтовый регистр, поэтому 0x00
загружается в +3
, и значение становится 0x0
.
#2 считывает данные в ax
. ax
— двухбайтовый регистр, поэтому загружается 0x00 0x02
и значение становится 0x200
.
Разница заключается в размере регистров назначения.
Один и тот же адрес загрузки (оба неэффективно используют 32-битную абсолютную адресацию, а не RIP-относительную), но один объединяет один байт в конец RAX, а другой объединяет 2 байта (слово).