Блочная сортировка как реализовать? - 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

Объяснение кода листинга программы

  1. Объявление секции LOCALS для определения локальных переменных
  2. Определение модели выполнения программы и размера стека
  3. Инициализация переменных в секции .data, включая массив A, содержащий 13 заранее заданных значений, и другие переменные.
  4. Инициализация процедуры main
  5. Загрузка адресного регистра ds и первоначальные шаги вывода исходного массива
  6. Сортировка массива с помощью процедуры bucketSort
  7. Вывод отсортированного массива
  8. Выход из программы Процедура bucketSort:
  9. Объявление локальных переменных
  10. Выделение памяти в стеке под переменные и сохранение регистров
  11. Производится блочная сортировка массива слов по указанной логике
  12. Восстановление регистров и освобождение памяти от локальных переменных Процедура ShowArray:
  13. Вывод массива слов на экран Процедура Show_AX:
  14. Подготовка числа для отображения (поиск количества цифр в числе и обработка отрицательных чисел)
  15. Вывод числа на экран, конвертированного в символьный формат Реализация программы заканчивается секцией end и выходом из процесса main.

Оцени полезность:

12   голосов , оценка 4 из 5