Блочная сортировка как реализовать? - Assembler
Формулировка задачи:
Нужна помощь в реализации алгоритма сортировки bucket sort на ассемблере x86 тасм
Решение задачи: «Блочная сортировка как реализовать?»
textual
Листинг программы
- LOCALS
- .model small, NOLANGUAGE
- .stack 1024h
- .data
- CrLf db 0Dh, 0Ah, '$'
- A dw 4, 25, 45, 11, 15, 73, 53, 59, 25, 23, 27, 99, 7
- ArSize equ ($-A)/2
- hor equ 10 ;т.к. остатки от деления на 10 в диапазоне 0..9
- ver equ ArSize+1
- .code
- main proc
- mov ax, @data
- mov ds, ax
- ;вывод исходного массива
- mov cx, ArSize
- lea dx, A
- call ShowArray
- mov ah, 09h
- lea dx, CrLf
- int 21h
- ;обработка - сортировка массива
- mov cx, ArSize
- lea dx, A
- call bucketSort
- ;вывод результата - отсортированного массива
- call ShowArray
- mov ah, 09h
- lea dx, CrLf
- int 21h
- mov ax, 4C00h
- int 21h
- main endp
- ;блочная сортировка массива слов
- ;на входе
- ; cx - длина массива
- ; ds:dx - указатель на массив
- bucketSort proc
- ;объявление переменных
- LOCAL buckets:word:(hor*ver), X:word, Count:word, Ten:word;
- ;выделение памяти в стеке под переменные (т.к. язык не указан - делаем вручную)
- push bp
- mov bp, sp
- sub sp, hor*ver*2+3*2 ;размер локальных переменных
- ;сохранение регистров
- push ax
- push bx
- push cx
- push dx
- push si
- push di
- ;вспомогательная переменная
- mov Ten, 10
- ;for(x=1; x<=100; x *= 10)
- mov X, 1
- @@ForX:
- ;всем элементам buckets присваиваем метку "не использовалось" значение (-1)
- push cx
- push es
- push ss
- pop es
- mov ax, -1
- lea di, ss:buckets
- mov cx, (hor*ver)
- rep stosw
- pop es
- pop cx
- ;count = 0 //обнуляем счётчик ячеек исходного массива чисел
- ;на самом деле Count - смещение в исходном массиве, а не просто индекс
- mov Count, 0
- ;for(i=0; i < size; i++)
- push cx
- push dx
- mov bx, dx ;задание базы для обращения к исходному массиву
- mov si, 0 ;i=0
- @@ForI:
- mov ax, [bx+si] ;ax=array[i]
- mov dx, 0 ;temp=array[i] / x
- div X
- mov dx, 0 ;oststok = temp % 10
- div Ten
- mov ax, dx ;ax - остаток от деления
- mov di, hor*2 ;получаем смещение в двумерном массиве
- mul di
- add ax, si
- mov di, ax ;di = смещение, соответствующее bucket[ostatok][i]
- mov ax, [bx+si] ;ax = array[i]
- mov buckets[di],ax ;buckets[oststok][i] = array[i]
- add si, 2 ;i++ (т.к. si - смещение, то увеличиваем на размер элемента)
- loop @@ForI
- pop dx
- pop cx
- ;вложенные циклы по всем элементам buckets проще представить
- ;одним циклом по всем элементам с индексом от 0 до (hor*ver-1)
- ;т.к. ячейки двумерного массива располагаются в памяти последовательно и
- ;построчно
- ;for(i=0; i<hor; i++)
- ; for(j=0; j<ver;j++)
- push cx
- push dx
- mov cx, (hor*ver)
- mov di, 0
- mov bx, dx
- @@ForIJ:
- mov ax, buckets[di] ;if (buckets[i][j] != -1
- cmp ax, -1
- je @@Skip
- mov si, Count ; array[count] = bucket[i][j]
- mov [bx+si], ax
- add Count, 2 ; count++
- @@Skip:
- add di, 2 ;i++, j++
- loop @@ForIJ
- pop dx
- pop cx
- mov ax, X ;X:= X*10
- add ax, ax ;ax = 2*X
- mov bx, ax ;bx = 2*X
- add ax, ax
- add ax, ax ;ax= 8*X
- add ax, bx ;ax = 10*X
- mov X, ax
- cmp X, 100
- ja @@BreakForX
- jmp @@ForX
- @@BreakForX:
- ;восстановление регистров
- pop di
- pop si
- pop dx
- pop cx
- pop bx
- pop ax
- ;освобождение памяти от локальных переменных
- mov sp, bp
- pop bp
- ;возврат из процедуры и освобождение памяти от аргументов
- ret 0
- bucketSort endp
- ;Вывод массива слов
- ;cx - количество выводимых элементов
- ;ds:dx - адрес массива
- ShowArray proc
- push ax
- push bx
- push cx
- push dx
- push si
- push di
- jcxz @@Exit ;если массив пустой - завершить
- mov si, 1 ;индекс элемента массива
- mov di, dx ;адрес текущего элемента массива
- @@ForI:
- mov ax, [di]
- call Show_AX
- mov ah, 02h
- mov dl, ' '
- int 21h
- ;переход к следующему элементу
- inc si
- add di, 2
- loop @@ForI
- @@Exit:
- pop di
- pop si
- pop dx
- pop cx
- pop bx
- pop ax
- ret
- ShowArray endp
- ; выводит число из регистра AX на экран
- ; входные данные:
- ; ax - число для отображения
- Show_AX proc
- push ax
- push bx
- push cx
- push dx
- push di
- mov cx, 10
- xor di, di ; di - кол. цифр в числе
- ; если число в ax отрицательное, то
- ;1) напечатать '-'
- ;2) сделать ax положительным
- or ax, ax
- jns @@Conv
- push ax
- mov dx, '-'
- mov ah, 2 ; ah - функция вывода символа на экран
- int 21h
- pop ax
- neg ax
- @@Conv:
- xor dx, dx
- div cx ; dl = num mod 10
- add dl, '0' ; перевод в символьный формат
- inc di
- push dx ; складываем в стэк
- or ax, ax
- jnz @@Conv
- ; выводим из стэка на экран
- @@Show:
- pop dx ; dl = очередной символ
- mov ah, 2 ; ah - функция вывода символа на экран
- int 21h
- dec di ; повторяем пока di<>0
- jnz @@Show
- pop di
- pop dx
- pop cx
- pop bx
- pop ax
- ret
- Show_AX endp
- end main
Объяснение кода листинга программы
- Объявление секции LOCALS для определения локальных переменных
- Определение модели выполнения программы и размера стека
- Инициализация переменных в секции .data, включая массив A, содержащий 13 заранее заданных значений, и другие переменные.
- Инициализация процедуры main
- Загрузка адресного регистра ds и первоначальные шаги вывода исходного массива
- Сортировка массива с помощью процедуры bucketSort
- Вывод отсортированного массива
- Выход из программы Процедура bucketSort:
- Объявление локальных переменных
- Выделение памяти в стеке под переменные и сохранение регистров
- Производится блочная сортировка массива слов по указанной логике
- Восстановление регистров и освобождение памяти от локальных переменных Процедура ShowArray:
- Вывод массива слов на экран Процедура Show_AX:
- Подготовка числа для отображения (поиск количества цифр в числе и обработка отрицательных чисел)
- Вывод числа на экран, конвертированного в символьный формат Реализация программы заканчивается секцией end и выходом из процесса main.
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д