Я новичок в сборке и пытался работать с массивом. Однако меня поймали при попытке сравнить значение массива с константой, хранящейся в регистре.
Судя по следующему коду, я ожидал, что программа перейдет после сравнения, поскольку значение в массиве, похоже, соответствует литералу в esi. Мой код выглядит следующим образом.
global _start
section .data
yay: db "It Worked!",0xA
array1: db 1, 2, 3, 4
section .bss
section .text
_start:
mov eax, [array1 + 1]
mov esi, 2
cmp eax, esi
je .equal
jmp _done
.equal:
mov eax, 4
mov ebx, 0
mov ecx, yay
mov edx, 11
int 0x80
jmp _done
_done:
mov eax, 1
mov ebx, 0
int 0x80
Буду очень признателен за любые советы относительно ошибок в моем коде!
Или сравните 0x00040302
, который вы видите с помощью отладчика, — это значение, которое вы загрузили в EAX. Обратите внимание, что младший байт — это 2
, старшие байты — это более поздние элементы массива (поскольку x86 имеет прямой порядок байтов). Я предполагаю, что компоновщик заполнен хотя бы одним 0
после окончания .data
.
Не связано с ошибкой: не знаю насчет насма, но для масма после :
не должно быть array1
.
@rcgldr NASM всегда принимает двоеточие после метки.
@ecm Использует ли mov eax, [array + 1] dword из-за размера eax или что-то еще?
@Jeremy Да, eax
— это 32-битный регистр, поэтому, когда он соединен с операндом памяти, этот операнд памяти также является 32-битным (что равно dword
). За исключением movzx
и movsx
, которые предназначены для расширения грузов. Вы можете написать свою инструкцию как mov eax, dword [array + 1]
, чтобы указать размер в NASM явно, если вы хотите получить доступ к dword.
@ecm — является ли двоеточие после метки данных необязательным в nasm? В masm без двоеточия вы получаете тип и размер массива, с двоеточием — это просто смещение без типа и размера.
@rcgldr Двоеточие необязательно. NASM не различает метки «данные» и метки «код». Этикетки в NASM никогда не имеют типа или размера. Метка без двоеточия и другого текста (без комментариев) в строке вызывает предупреждение orphan-label
: nasm.us/xdoc/2.16.03/html/nasmdoca.html Я пытался добавить более общее label-no-colon
предупреждение, но оно еще не объединено: bugzilla.nasm.us/show_bug.cgi?id=3392632
Причина, по которой ваш код неправильно загружает значение, расположенное по первому индексу вашего массива, в EAX
, заключается в том, что массив находится в сборке. В ассемблере, когда вы определяете «массив», вы просто помещаете данные в память. Хотя это может показаться очевидным, это также означает, что между элементами НЕТ разделителя («строка» также является массивом). Это означает, что когда вы выполняете MOV EAX, [ARRAY1 + 1]
без указания размера операции, nasm просматривает контекст инструкции, чтобы определить размер. Поскольку вы используете 32-битный регистр, размер по умолчанию равен DWORD
. Это означает, что инструкция загрузит 32 бита (4 байта) из вашего массива, начиная с [ARRAY1 + 1]
. Чтобы предотвратить это, вам нужно указать размер вашей операции в байтах, выполнив MOVZX EAX, BYTE [ARRAY1 + 1]
. Вам нужно использовать MOVZX
, чтобы заполнить остальную часть регистра нулями.
Первое, что мне бросается в глаза в вашем коде, это использование JMP
прямо перед меткой, по которой вы переходите. В этом нет необходимости, поскольку выполнение продолжится до метки. Это связано с тем, что метки — это не «функции», а просто маркеры, представляющие адреса памяти. В собранной программе их нет. Во-вторых, хотя это и не важно, вместо MOV EAX, 0
это выполняется немного быстрее XOR EAX, EAX
. Наконец, у вас есть пустой раздел BSS
, он не нужен компоновщику и его можно просто оставить (по крайней мере, для ld).
«размер по умолчанию равен WORD
». Неверно, на 386 из-за происхождения 8086 word
— это то, что мы называем 16-битной величиной, и, следовательно, double word
или dword
— это 32-битная величина. Регистр eax
имеет размер dword
.
Да, спасибо, что отметили это
db
представляет собой массив байтов, как и адресация+ 1
. Итак,mov eax, [array1 + 1]
неверен, поскольку загружает двойное слово (4 байта). Либо переключитесь наdd
иmov eax, [array1 + 4]
, либо используйтеmovzx eax, byte [array1 + 1]
.