Member 12569032 Ответов: 3

Реверсивные элементы массива в сборе


Привет,

Я пытаюсь реверсировать элемент массива в сборке, вот мой код:

.data
	
	array DWORD 1, 5, 6, 8, 0Ah, 1Bh, 1Eh, 22h, 2Ah, 32h  ;array to be reversed

.code
main proc
       mov esi, 0
	mov edi, 0
	mov eax, 0
	mov ebx, 0

	mov esi, OFFSET array							;move first element address to esi
	mov edi, OFFSET array + SIZEOF array - TYPE array  ;move last element address to edi
	
	mov ecx, LENGTHOF array / 2     ;sets the counter in the reverseLoop

reverseLoop:
	mov eax, [esi]    ;move the element in esi to eax
	mov ebx, [edi]	  ;move the element in edi to ebx

	xchg eax, ebx     ;exchange the two elements

	mov [esi], eax  ;move the element in eax, to the address in esi
	mov [edi], ebx  ;move the element in ebx, to the address in edi

	add esi, TYPE array ;increase esi to take the next element in the array (from the left)
	sub edi, TYPE array ;decrease edi to take the next element in the array (from the right)

	loop reverseLoop

	invoke ExitProcess,0
main endp
end main</pre> 


Этот код работает до сих пор с массивом DWORD, однако, если я изменяю размер массива на байт, я получаю проблему. В первой строке в reverseLoop, "mov eax, [esi]", регистр eax не получает первый элемент в массиве, как это было раньше, когда размер массива был DWORD. Вместо этого он, кажется, получает какое-то случайное число. Есть идеи, почему он это делает?

Что я уже пробовал:

Я действительно не мог понять, в чем проблема.

PIEBALDconsult

Вы не должны были удалять исходную версию этого вопроса; вы должны были использовать "улучшить вопрос".

Member 12569032

Я сделал это, но случайно удалил вопрос, а затем попытался улучшить, но потом увидел, что он был удален.

3 Ответов

Рейтинг:
2

Patrice T

Прежде всего, вы можете упростить свой код

reverseLoop:
	mov eax, [esi]    ;move the element in esi to eax
	mov ebx, [edi]	  ;move the element in edi to ebx
 
	xchg eax, ebx     ;exchange the two elements
 
	mov [esi], eax  ;move the element in eax, to the address in esi
	mov [edi], ebx  ;move the element in ebx, to the address in edi
 
	add esi, TYPE array ;increase esi to take the next element in the array (from the left)
	sub edi, TYPE array ;decrease edi to take the next element in the array (from the right)
 
	loop reverseLoop

около
reverseLoop:
	mov eax, [esi]    ;move the element in esi to eax
	mov ebx, [edi]	  ;move the element in edi to ebx
 
	xchg eax, ebx     ;exchange the two elements
 
	mov [esi], ebx  ;move the element in ebx, to the address in esi
	mov [edi], eax  ;move the element in eax, to the address in edi
 
	add esi, TYPE array ;increase esi to take the next element in the array (from the left)
	sub edi, TYPE array ;decrease edi to take the next element in the array (from the right)
 
	loop reverseLoop


Во-вторых, почему вы не используете регистры байтового размера для перемещения байтов ?
Нравится AL или AH и BL или BH ?
Я знаю, это старомодно, но для меня это выглядит наиболее прямолинейно.

[Обновление]
Чтобы обрабатывать все возможности как можно быстрее, вам нужен такой код, как:
if (TYPE is DWORD)
    optimized code for DWORD (mostly your sample code)
else if (TYPE is WORD)
    optimized code for WORD
else if (TYPE is BYTE)
    optimized code for BYTE
end if


Чтобы обрабатывать все возможности с помощью одного фрагмента кода, Вы должны работать с наименьшим возможным размером данных. Это возможно, но будет медленным.
array DWORD 1,2,3,4,5,6,7,8,9,10,11,12

буду давать
array DWORD 9,10,11,12,5,6,7,8,1,2,3,4


array WORD 1,2,3,4,5,6,7,8,9,10,11,12

буду давать
array WORD 11,12,9,10,7,8,5,6,3,4,1,2


array BYTE 1,2,3,4,5,6,7,8,9,10,11,12

буду давать
array BYTE 12,11,10,9,8,7,6,5,4,3,2,1

в вашем основном цикле вам нужен другой цикл для обработки различных размеров данных.
reverseLoop:
    for dx=1 to (TYPE array)
        mov ah, [esi]    ;move the element in esi to ah
        mov bh, [edi]	  ;move the element in edi to bh
 
        mov [esi], bh  ;move the element in bh, to the address in esi
        mov [edi], ah  ;move the element in ah, to the address in edi
        add esi, 1
        add esi, 1
    next
    sub edi, TYPE array
    sub edi, TYPE array ;decrease edi to take the next element in the array (from the right)
 
    loop reverseLoop

Псевдокод, я позволяю вам иметь дело с деталями


Member 12569032

В моем задании предполагается, что мой код будет работать для любого размера массива

Patrice T

Размер массива или размер элементов ?

Member 12569032

Я имею в виду размер элементов. Каждый элемент в массиве может иметь любой размер, байт или DWORD в зависимости от того, какой размер вы объявите массиву.

Karthik_Mahalingam

5

Рейтинг:
2

Member 13540174

mov esi, 0
mov edi, 0
mov eax, 0
mov ebx, 0

mov esi, OFFSET array ;переместить адрес первого элемента в esi
mov edi, OFFSET array ;переместить адрес последнего элемента в edi

mov ecx, массив LENGTHHOF ;устанавливает счетчик в обратном цикле

reverseLoop:
mov eax, [esi] ;переместить элемент в esi в eax
mov ebx, [edi] ;переместить элемент в edi в ebx
добавьте esi, введите array ;увеличьте esi, чтобы взять следующий элемент в массиве (слева)
sub edi, введите array ;уменьшите edi, чтобы взять следующий элемент в массиве (справа)
вызов writehex
называть символы не экранируются
петля reverseLoop


Рейтинг:
0

OriginalGriff

mov eax, [esi]загружает eax со значением DWORD, а не байтом.
И это реальная проблема, потому что байтовые указатели не ограничиваются адресами DWORD.
DW-слова всегда находятся на адресе, кратном 4, байтовые адреса-кратны одному. Поэтому, когда вы передаете байтовый адрес инструкции DWORD, загруженное значение не является байтом, и это не четыре байта, начинающиеся с этого адреса. Это четыре байта, начиная с байтового адреса, округленного до предыдущего кратного четырем.
Так что это выглядит как случайные данные, но это не так!
Используйте байтовый доступ с байтовыми данными.


Member 12569032

Есть идеи, как заставить код работать для любого размера массива?