Перенести в начало массива все положительные элементы - Assembler
Формулировка задачи:
Доброго времени суток. Нужно перенести в начало массива все положительные элементы
Мой код:
Выводит 3, -1, -2, 4, 5, 6, 7, 8, 9, 7
А должен, естественно, 3, 4, 5, 6, 7, 8, 9, 7, -1, -2
Что я делаю не так, где ошибка?
Благодарю.
include "D:\prog\fasmw\INCLUDE\win32ax.inc"
.data
ar dd -1, -2, 3, 4, 5, 6, 7, 8, 9, 7
caption1 db "Массив = %d %d %d %d %d %d %d %d %d %d ", 0
tr db 50 DUP(?)
.code
main:
mov esi, 0 ;; для проверки знака
mov ebx, -4 ;; нулевой элемент массива
mov edx, 36 ;; для проверки конца массива
l1:
add ebx, 4
cmp [ar+ebx] , esi ;; esi == 0, проверки больше 0
jl m1
jmp l1
m1: mov eax, ebx ;; для временного использования
lm1:
cmp [ar+eax+8] , edx ;; edx == 36, проверка конца массива
jl continue
jmp exit
continue:
cmp [ar+eax+4], 0 ;; находим потом положительные для свапа
jg swapp
jmp m2
swapp:
mov edi, [ar+ebx] ;; edi = [temp]
mov edx, [ar+eax+4]
mov [ar+ebx], edx
mov [ar+eax+4], edi
jmp l1
m2:
add eax, 4
jmp lm1
exit:
invoke wsprintfA, addr tr, addr caption1, [ar+0], [ar+4], [ar+8], [ar+12], [ar+16], [ar+20], [ar+24], [ar+28], [ar+32], [ar+36]
invoke MessageBoxA, 0, addr tr, addr caption1, 0
invoke ExitProcess, 0
.end mainРешение задачи: «Перенести в начало массива все положительные элементы»
textual
Листинг программы
format PE GUI 4.0 entry Start include 'win32a.inc' section '.text' code readable executable Start: cld ; направление mov esi,ar ; адрес начала массива mov ecx,Cycle ; циклов @@: ; пихаем всё в стек lodsd push eax loop @r mov edi,ar ; адрес начала массива mov ecx,Cycle ; циклов mov esi,Adr_ar_end ; смещение на конец массива sortir: ; сортируем из стека pop eax cmp eax,0 jb minus stosd ; в цепочку с начала jmp @f minus: mov [esi],eax ; в цепочку с конца sub esi,4 ; адрес конца +4 @@: loop sortir invoke wsprintfA, tr, caption1, [ar+0], [ar+4], [ar+8], [ar+12], [ar+16], [ar+20], [ar+24], [ar+28], [ar+32], [ar+36] invoke MessageBoxA, 0,tr,Title, 0 invoke ExitProcess, 0 section '.data' data readable writeable ar dd -1, -2, 3, 4, 5, 6, 7, 8, 9, 7 Cycle = ($-ar)/4 ; число циклов Adr_ar_end = ar+Cycle*4-4 ; адрес последнего элемента Title db 'Заголовок',0 caption1 db "Массив = %d %d %d %d %d %d %d %d %d %d ", 0 tr db 50 DUP(?)
Объяснение кода листинга программы
Предположительно данный код выполняет следующие действия:
- Задаёт направление (cld).
- Инициализирует переменные (mov esi,ar; mov ecx,Cycle).
- В цикле (while) сортирует массив по возрастанию (lodsd; push eax; loop @r).
- Выводит отсортированный массив на экран (invoke wsprintfA, tr, caption1, [ar+0], [ar+4], [ar+8], [ar+12], [ar+16], [ar+20], [ar+24], [ar+28], [ar+32], [ar+36]; invoke MessageBoxA, 0,tr,Title, 0; invoke ExitProcess, 0).
- Задаёт адрес начала массива (mov edi,ar), количество циклов (mov ecx,Cycle) и смещение на конец массива (mov esi,Adr_ar_end).
- В цикле (while) сортирует массив по убыванию (pop eax; cmp eax,0; jb minus; stosd; sub esi,4; loop sortir).
- Выводит отсортированный массив на экран (invoke wsprintfA, tr, caption1, [ar+0], [ar+4], [ar+8], [ar+12], [ar+16], [ar+20], [ar+24], [ar+28], [ar+32], [ar+36]; invoke MessageBoxA, 0,tr,Title, 0; invoke ExitProcess, 0).
- Инициализирует переменные (Title db 'Заголовок',0; caption1 db
Массив = %d %d %d %d %d %d %d %d %d %d, 0; tr db 50 DUP(?)). - Задаёт начальное значение переменной Cycle (Cycle = ($-ar)/4).
- Вычисляет адрес последнего элемента массива (Adr_ar_end = ar+Cycle*4-4).