Обратное содержимое массива в сборке

Я работаю над домашним заданием по сборке и застрял в своей последней программе. Если кто-то со знанием сборки x86 скрывается, пожалуйста, не стесняйтесь комментировать, как я могу начать с этого. Спасибо!

проблема:

Используйте цикл с косвенной или индексированной адресацией, чтобы поменять местами элементы целочисленного массива. не копируйте элементы ни в какой другой массив. Также используйте операторы SIZEOF, TYPE и LENGTHOF, чтобы сделать программу гибкой для различных массивов.

код пока:

.data
array BYTE 10h,20h, 30h, 40h

.code
main PROC
    call Clrscr

        ;no clue... 

    exit
main ENDP

END main

person darko    schedule 09.03.2011    source источник
comment
Возможно, начните с размышлений о том, как бы вы сделали это на языке, с которым вы более знакомы.   -  person Jerry Coffin    schedule 09.03.2011
comment
Напишите ответ на C, затем скомпилируйте на ассемблере и оживите его, чтобы он выглядел так, как будто вы его напечатали сами. :D   -  person JUST MY correct OPINION    schedule 10.03.2011
comment
вы можете использовать стек, чтобы поместить в него элементы и вытолкнуть их. например: arr db 3, 2, 1 push 3, push 2 и push 1 в стеке, а затем извлеките их и поместите в соответствующий индекс, начиная с начала.   -  person Ahtisham    schedule 16.11.2017
comment
вы можете использовать стек, чтобы поместить в него элементы и вытолкнуть их. например: arr db 3, 2, 1 push 3, push 2 и push 1 в стеке, а затем извлеките их и поместите в соответствующий индекс.   -  person Ahtisham    schedule 16.11.2017


Ответы (4)


Ну, укажите начало массива с esi и конец с edi, загрузите два.. элемента (?), поменяйте их местами, затем измените esi и edi соответственно и повторите до.... подсказка: вам не нужно менять местами ничего, так как вы в сборке =P

person BlackBear    schedule 09.03.2011
comment
не знаю, кто за тебя проголосовал. Голосуйте от меня, чтобы противодействовать этому. Спасибо за ответ! - person darko; 11.03.2011

Я не очень хорошо разбираюсь в ассемблере, поэтому может существовать лучший ответ (этот работает).

TITLE Reversing an array without using oneother array
INCLUDE Irvine32.inc

.data
    array1 DWORD 10d,20d,30d,40d,50d,60d,70d,80d,90d
.code
main PROC
        mov ESI, OFFSET array1  ;ESI now points to the first item of array1
        mov EDI, SIZEOF array1
        add EDI, OFFSET array1
        sub EDI, TYPE array1    ;EDI now points to the last item of array1

        mov ECX, LENGTHOF array1
        shr ECX, 1          ;now ecx is half the length of the array1
L1:     mov EAX, [ESI]          ;in this loop we reverse the items of the array
        mov EBX, [EDI]
        mov [EDI],EAX
        mov [ESI],EBX
        add ESI, TYPE array1
        sub EDI, TYPE array1
        LOOP L1

        mov ECX, LENGTHOF array1;here we just print the array
        mov ESI, OFFSET array1
L2:     MOV EAX, [ESI]
        call WriteInt
        call Crlf
        add ESI, TYPE array1
        LOOP L2
        exit        
main ENDP
END main
person captain monk    schedule 02.09.2015
comment
Да, за исключением того, что вам не нужно медленная инструкция loop. Просто cmp esi, edi/jb L1 для цикла, пока начальный указатель находится ниже конечного указателя. Настройка указателя также может быть проще: либо поместите метку в конец массива, либо mov edi, OFFSET array1 + SIZEOF array1 - TYPE array1, чтобы выполнить все эти вычисления при сборочном типе. - person Peter Cordes; 14.11.2017

Профессионал будет использовать специальные строковые инструкции и регистры источника и назначения; но это, вероятно, будет выглядеть так, как будто вы обманули свою домашнюю работу.

Ниже приведены основные мемоники, которые вы можете использовать для достижения своей цели:

  • Источник назначения MOV

    MOV eax,array загружает адрес массива в eax

    MOV edx,[eax] загружает значение, на которое указывает eax, в edx

  • INC eax увеличивает значение в eax на единицу

  • ИЛИ eax, eax (устанавливает нулевой флаг, если eax равен нулю)

  • Метка JZ (переходит к метке, если установлен нулевой флаг)

Метка устанавливается путем добавления двоеточия ":", например label:

person Bernd Elkemann    schedule 09.03.2011
comment
Под специальными строковыми инструкциями вы имеете в виду movs*? Я слышал, что они устарели - person BlackBear; 10.03.2011
comment
Устаревший, поскольку, возможно, наносит ущерб современным конвейерам, но по-прежнему предлагает элегантные и простые решения. - person Jens Björnhager; 10.03.2011
comment
не говоря о МОВС. говоря о микрокоде с использованием R/ESX и R/EDX. кроме того: вопрос или мой ответ вовсе не об этом. - person Bernd Elkemann; 10.03.2011
comment
@eznme, не знаю, кто за тебя проголосовал. Голосуйте от меня, чтобы противодействовать этому. Спасибо за ответ! - person darko; 11.03.2011
comment
Профи будет использовать 4-байтовые загрузки и bswap для реверсирования 4 байтов в регистре. Вы можете рассмотреть lodsd для одной из загрузок и приращений указателя, но только на Haswell и новее, где это всего 2 моп. (То же, что mov eax, [esi] / add esi,4). Кроме того, используйте test eax,eax, чтобы проверить, равен ли EAX нулю; or same,same хуже. Но это не имеет смысла, потому что в предложенном вами коде это указатель, а не индекс. - person Peter Cordes; 07.10.2019
comment
Большинство процессоров в наши дни имеют SSSE3, и если это так, вы можете реверсировать байты (или реверсировать двойные слова) 16 байтов за раз. Ваш ответ предлагает выполнять 4-байтовые загрузки, но также предлагает inc eax, который продвигается только на 1 байт. Инструкции rep-string здесь бесполезны: все они используют один и тот же флаг направления, но вам нужно читать в обоих направлениях и писать в обоих направлениях для реверса на месте. Четное или одиночное movsd бесполезно. И stosd медленнее, чем нужно. - person Peter Cordes; 07.10.2019

person    schedule
comment
Хотя этот код может решить проблему, включая объяснение того, как и почему это решает проблему, действительно поможет улучшить качество вашего сообщение и, вероятно, приведет к большему количеству голосов. Помните, что вы отвечаете на вопрос для будущих читателей, а не только для того, кто задает сейчас. Пожалуйста, отредактируйте свой ответ, чтобы добавить пояснения и указать, какие ограничения и предположения применяются. - person Suraj Rao; 07.10.2019
comment
mov ebx,[ax] не собирается; 16-битные режимы адресации не могут использовать AX в качестве базы или индекса. И это 32-битный код, поэтому вы почти наверняка ошибетесь, если вы используете действительный регистр, но все равно усекаете 32-битный адрес метки до 16-битного. Кроме того, в этом цикле нет никаких инструкций по сохранению, только бесполезные xchg и reg-reg перемещения. И супер-странные dec ecx / loop вместо того, чтобы использовать length / 2 в качестве счета в первую очередь, или ходить по 2 указателям, пока они не пересекутся, как нормальный человек. Я проголосовал за это только из-за неэффективности (и отсутствия объяснения), прежде чем заметил, что оно полностью сломано! - person Peter Cordes; 07.10.2019