Как я мог это сделать?
(вопрос из комментариев к самостоятельному ответу)
Ну, сначала вы читаете Справочник по инструкции, чтобы понять, что делает инструкция, а затем вы можете использовать ее, если она соответствует вашей цели. Это важный шаг, продолжайте время от времени перечитывать детали инструкции, чтобы убедиться, что она изменяет регистры и флаги так, как вы ожидаете. Особенно, если в отладчике вы видите изменение состояния процессора, которого не ожидали.
Поскольку вы работаете в Linux, регистры сегментов ds/es, скорее всего, уже имеют разумные значения (охватывающие раздел .data), поэтому после установки eSi на Sисходный адрес, eDi на D strong>адрес назначения и eCx до Cколичества, вы пишете вместо COPY_LOOP: просто rep movsb ... и затем выходите через int 80h (eax=1). (обратите внимание на подчеркнутые буквы в именах регистров, Intel выбрала их намеренно, чтобы их было легко вспомнить)
Кстати, только сейчас я заметил, что вы написали в своем коде ошибки:
inc si/di должно быть inc esi/edi, потому что вы используете esi/edi для адресации. Если бы вы копировали массив с границей памяти 64 КБ, inc si зациклился бы на нем.
установите ecx на 3, в режиме 32b инструкция loop использует всю 32b ecx, а не только часть 16b cx. Если код перед копированием будет использовать какое-то большое число в ecx, устанавливая некоторые из старших 16 бит, ваш цикл скопирует гораздо больше байтов, чем только 3.
перед повторным вызовом int 80h вы должны установить целое eax с номером функции, иначе вы рискуете получить мусор в старших 16 битах eax из предыдущего кода, запрашивая неверную функцию.
Итак, после их применения ваш код может выглядеть так:
section .text
global _start
cpu 386
_start:
MOV ESI, TABLE_A
MOV EDI, TABLE_B
MOV ECX, 3
REP MOVSB ; copy ECX bytes from DS:ESI to ES:EDI
MOV EAX,1 ; call sys_exit, again FIXED to EAX!
INT 80h
section .data
TABLE_A DB 10, 5, 1
TABLE_B DB 0, 0, 0
Если вы читали документацию о регистрах, вы уже должны понимать, в чем разница между eax и ax. В Linux вы находитесь в режиме 32b (когда вы связываете двоичный файл как 32b elf, в настоящее время 64b может быть по умолчанию в системе 64b, что немного отличается от режима 32b), поэтому по умолчанию используйте варианты регистров 32b. Если вам действительно не нужен вариант 16b/8b по определенной причине, и вы убедитесь, что код не работает позже с регистром 32b, пока вы устанавливаете только меньшее его значение (например, loop, rep movsb и int 80h).
Кроме того, это обычно делает код быстрее, так как использование 16b ax в режиме 32b требует дополнительного байта кода операции перед инструкцией, например, mov eax,ebx — это 2 байта кода операции 89 D8, mov ax,bx — это 3 байта кода операции 66 89 D8.
29.10.2016
dsиesуказывают на сегмент .data (а DF=DirectionFlag равен нулю), то вы можете заменить весь COPY_LOOP одной инструкцией с префиксом повторенияrep movsb. 27.10.2016mov ax,1потенциально сломан; используйтеmov eax,1, чтобы установить номер вызова, не оставляя никакого старшего мусора в старших 2 байтах. То же самое для CX; ваш цикл использует ECX, но вы устанавливаете только младшие 2 байта; вы можете зациклить несколько кратных 2 ^ 16 раз больше, чем вы имели в виду. 24.04.2021rep movsb: DS и ES уже настроены корректно под линуксом, можно буквально просто запуститьrep movsb24.04.2021