Седов Иван Алексеевич
Рязанский политехнический колледж
ASSEMBLER 8-bit SIMULATOR
Занятие #8: создание процедуры
сортировка массива по возрастанию

https://e1m7.github.io/work/
Последнее занятие по ассемблеру будет посвящено сложной и интересной процедуре сортировки одномерного массива по возрастанию. Для решения этой задачи мы напишем несколько вспомогательных процедур, которые позволят решить эту задачу за пару шагов
- процедура array_print (вывод массива)
- процедура array_length (нахождение длины массива)
- процедура array_sort (сортировка массива)
Для простоты мы договоримся, что массив это набор байт, каждый из которых является числом от 0 до 9. Можно задавать полные байты (0-255), но выводить массив на печать будет не удобно. (Однако, в оперативной памяти массив упорядочится верно.)
Суть программы будет такова:
1) Получаем адрес массива (байты 48-57), на конце '#' (код 35)
2) Находим длину массива (нужна для сортировки)
3) Выводим массив на экран (экран: 2 1 3)
4) Сортируем по возрастанию (магия)
5) Выводим массив на экран (экран: 1 2 3)
array: DB 2
DB 1
DB 3
DB '#'
; 2 1 3 (до сортировки)
; 1 2 3 (после сортировки)array_print:
; input
; C = array of number, '#'
PUSH A
PUSH C
PUSH D
MOV D, 232 ; D=232 (настройка на байты вывода)
.loop100:
MOV A, [C] ; A=байт, адрес которого в C
ADD A, '0' ; A=A+'0'=значение байта + 48
CMP A, 83 ; Сравнение: A=83? 83=35(#)+48(0)
JE .exit101 ; (да) переход на .exit101
MOV [D], A ; (нет) байт, адрес которого в D=A
INC D ; D=D+1
INC C ; C=C+1
JMP .loop100
.exit101:
POP D
POP C
POP A
RETВопрос: а зачем нам нужна процедура array_length? Да, она найдет нам длину массива (допустим, он состоит из 6 элементов). Но давайте разберемся...
Если мы будем брать текущий индекс элемента и сравнивать значение текущего элемента и значение следующего элемента, то какой индекс будет для нас "остановочным"?
Если на 6-ом месте (под индексом 5) стоит минимальное число (в данном случае 1), то сколько проходов-сравнений надо будет сделать, чтобы она встала на 1-ое место (под индексом 0)?
arr: DB 6, 5, 4, 3, 2, 1, #
; 0 1 2 3 4 5 6array_length:
; input
; C = array of number, '#'
; output
; A = length array
PUSH B
PUSH C
XOR A, A ; A=0 (XOR 11=>0, 10=>1, 01=>1, 00=>0)
.loop110:
MOV B, [C] ; B=байт, адрес которого в С
CMP B, 35 ; Сравнение: B=35? (это решетка?)
JE .exit111 ; (да) перейти на выход
INC A ; (нет) A=A+1 (накопить счетчик)
INC C ; С=С+1 (перейти на следующий элемент)
JMP .loop110
.exit111:
DEC A ; A=A-1 (нам нужно именно это число)
POP C
POP B
RETПроцедура array_sort оказалась длинной (вся программа 173 байта, 130 строк кода), записывать ее лучше сразу с основной программой (надо будет добавить две ранее записанные процедуры array_print и array_length в самый низ).
JMP start
arr: DB 6
DB 5
DB 4
DB 3
DB 2
DB 1
DB '#'
len: DB 0start:
MOV C, arr
CALL array_length
MOV [len], A
CALL array_print ; Вывод массива
CALL array_sort ; Сортировка
CALL array_print ; Вывод массива
HLT
array_sort:
; input
; C = array of number, '#'
; len = length - 1
PUSH A
PUSH B
PUSH C
PUSH D ; Внешний цикл
MOV C, 0
.loop600:
CMP C, [len]
JE .exit601
; Внутренний цикл
MOV D, 0
.loop602:
CMP D, [len]
JE .exit602
; Извлечение чисел
MOV A, arr ; A=arr (адрес)
ADD A, D ; A=A+D (адрес + смещение)
MOV B, [A] ; B=по адресу A (1-ое число)
PUSH B ; 1 число => в стек
MOV B, [A+1] ; B=по адресу A+1 (2-ое число)
POP A ; 1 число <= из стека ; A=1-ое число (текущее)
; B=2-ое число (текущее+1)
; Сравнение чисел
CMP A, B ; Сравнить: A>B?
JA .change666 ; (да) переход .change666
JMP .exit666 ; (нет) переход .exit666
; Обмен чисел
.change666:
PUSH A ; 1 => стек
PUSH B ; 2 => стек (2,1)
MOV A, arr ; A=arr (адрес)
ADD A, D ; A=A+D (адрес + смещение)
POP B ; B=2-ое число
MOV [A], B ; Адрес 1 = 2 число
POP B ; B=1-ое число
MOV [A+1], B ; Адрес 2 = 1 число .exit666:
INC D
JMP .loop602
; Внутренний цикл
.exit602:
INC C
JMP .loop600
; Внешний цикл
.exit601:
POP D
POP C
POP B
POP A
RET- print_string
-
print_number
-
print_char
- remainder_division
-
remdiv10
- halt
- string_to_number
- number_to_string
- factorial
- fibonachi
- array_print
- array_length
- array_sort
Замечание
В нашем распоряжении есть процедуры:
Введение в программирование окончено!!!
assembler8_08
By Ivan Sedov
assembler8_08
- 462