Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Центр помощи > [Assembler] Сортировка массива


Автор: seven65 1.12.2006, 16:49
Написать программу на языке Ассемблер, в которой осуществляется обработка исходного массива (10 – 15 элементов) и формирование массива результата. Размерность элементов исходного массива и массива результата – WORD.
Действия для предварительной обработки элементов исходного массива выбирается из таблицы 1.
Условия поэлементного формирования массива результата из таблицы 2.
Выбор способов адресации выбирается из таблицы 3.

1)
Способ обработки:
В исходном массиве переставить элементы так, чтобы они располагались в следующем порядке.  
Отрицательные и положительные элементы исходного массива в порядке их расположения меняются местами.

2)
Условия формирования массива результата.
Элемент исходного массива помещается в массив результата если его значение:
больше среднего арифметического наибольшего и последнего элемента исходного массива.

После отладки программы изменить е+- для обработки данных  размерности DWORD.

3)
Способ адресации.
Обработка исходного массива - индексная.
Формирование массива результата - базовая. 

Автор: anwe 9.12.2006, 21:35
По многочисленным просьбам сделал.
Программка делает то, что просил. Элементы исходного массива заданы произвольно так же, как и их количество.
Среднее арифметическое вычислено с использованием целочисленной арифметики, вернее используется следующее свойство: среднее арифметическое двух целых чисел будет либо целым числом либо иметь дробную часть 5/10.
В условии задачи написано, чтобы элементы нового массива были больше этого среднего арифметического. Поэтому целочисленной арифметики хватает.
Пусть при делении на 2 получил 5,5, что в целочисленной арифметике означает частное равно 5 плюс какой-то остаток. Значит для удовлетворения условию задачи элемент должет быть просто больше 5 (ведь 6>5,5), значит применяемое условие будет "больше". Но это для положительных чисел. Для отрицательных не так.
Пусть среднее арифметическое равно -5,5. Частное равно -5. Если возмешь -4, это будет верно, но также и -5>-5,5. Значит в случае с отрицательными числами надо брать не только большие, чем частное, но и числа равные частному. Значит применяемое условие будет "больше или равно".
Чтобы такой отбор сделать в одном цикле, то есть использовать одно условие, надо "оттянуть" частное, если оно отрицательное, на 1 влево, то есть уменьшить его. Для этого примера получим частное -6. Тогда одно условие "больше" можно применить и для отрицательных и для положительных чисел. Это и делает часть кода
Код

    cmp    sign,1000000000000000b
    jne    l4
    dec    ax
l4:

И последнее. Для преобразования исходного массива (и нового соответственно) в размер двойных слов надо:
1. Расширить все регистры размерности слова до двойного путем дабавления е.
2. Изменить 2->4.
3. Изменить 1->2, но только в делении. В командах inc и dec ничего не менять!
4. При определении знака добить еще 16 нулей.
5. Переделать блоки вывода массивов под размерность двойных слов (это еще одно сохранение, сдиг и восстановлени выводимого символа по подобию, как это уже сделано).
6. Заменить размерности массива, нового массива и знаков (не длинн).

Сам код:
Код

    .model tiny
    .code
    .386
    org 100h
start:
    movzx    ecx,len        ;для цикла заносим длину массива
    shr    ecx,1        ;так как длина в словах делим на 2
    dec    cl        ;сравниваем со следующим, значит на 1 меньше
    xor    esi,esi        ;начальное значение индекса 0
    lea    ebx,massiv        ;заносим адрес массива
l1:
    mov    ax,[ebx+esi*2]    ;считываем первый элемент
    and    ax,1000000000000000b    ;проверяем старший бит - знак
    mov    sign,ax        ;сохраняем его
    mov    dx,[ebx+esi*2+2]    ;считываем второй элемент
    and    dx,1000000000000000b
    cmp    dx,sign        ;сравниваем знаки
    je    l2        ;если равны идем дальше
    mov    ax,[ebx+esi*2]    ;если нет берем предыдущий элемент
    xchg    [ebx+esi*2+2],ax    ;в меняет со следующим
    mov    [ebx+esi*2],ax    ;заносим в предыдущий
    jmp    l2
l2:
    inc    esi        ;увеличиваем индекс
    loop    l1
;------------------------
;блок вывода исходного массива после обработки
;------------------------
    movzx    ecx,len        ;для вывода нужны все элементы
    shr    ecx,1
    xor    esi,esi
l3:
    mov    ax,[ebx+esi*2]    ;считываем элемент
    push    ax
    xchg    ah,al
    call    print_all        ;вывод старшей цифры
    pop    ax
    call    print_all        ;вывод младшей цифры
    inc    esi        ;увеличиваем индекс
    loop    l3
    mov    dx,offset ctrl        ;адрес строки перевода
    mov    ah,09h        ;перевести строку
    int    21h
;------------------------
;Блок вычисления максимального и среднего арифметического
;максимального и последнего элемента
;------------------------
    movzx    ecx,len
    shr    ecx,1
    dec    cl
    push    ebx        ;адрес массива еще понадобится
    push    ebx
    mov    ax,[ebx]        ;считываем первый элемент
    add    ebx,2        ;переходим к следующему
l6:
    cmp    ax,[ebx]        ;сравниваем со следующим
    jg    l5        ;больше?
    mov    ax,[ebx]        ;нет - заносим в регистр
l5:
    add    ebx,2        ;да - переходим к следующему
    loop    l6
    pop    ebx
    push    eax        ;это наибольший элемент
    movzx    eax,len
    sub    eax,2
    add    ebx,eax        ;перемещаемся на последний элемент
    pop    eax
    add    ax,[ebx]        ;добавляем к наибольшему
    push    ax
    and    ax,1000000000000000b    ;определяем знак
    mov    sign,ax
    pop    ax
    shr    ax,1        ;делим на 2 - среднее арифметическое двух чисел
    or    ax,sign            ;устанавливаем знак
    cmp    sign,1000000000000000b    ;знак минус?
    jne    l4            ;нет - идем дальше
    dec    ax            ;да - увеличиваем среднее
l4:
    pop    ebx
    lea    ebp,massiv1        ;заносим адрес нового массива
    push    ebp
    movzx    ecx,len        ;заносим длину исходного массива
    shr    ecx,1
l8:
    mov    dx,[ebx]        ;считываем элемент исходного массива
    cmp    dx,ax        ;он больше среднего арифметического?
    jle    l7        ;нет - идем дальше
    mov    [ebp],dx        ;да - заносим его в новый массив
    add    ebp,2        ;переводим указатель на следующий элемент нового массива
    inc    len1        ;изменяем длину нового массива
l7:
    add    ebx,2        ;переходим к следующему элементу исходного массива
    loop    l8
    pop    ebp
    movzx    ecx,len1        ;длина нового массива
    test    ecx,ecx        ;она равна нулю?
    jz    l10        ;да - выход
l9:
    mov    ax,[ebp]        ;нет - считываем
    push    ax        ;и выводим
    xchg    ah,al        ;этот уже проходили
    call    print_all
    pop    ax
    call    print_all
    add    ebp,2
    loop    l9
l10:
    ret
;------------------------
;Блок вывода цифр. Выводит в 16-ричной системе.
;Отрицательные выводит согласно 16-ричной системы.
;------------------------
print_all:
    mov    dh,al        ;сохраняем
    and    dh,0Fh        ;младшую цифру
    shr    al,4
    call    print_n        ;вывод старшей цифры
    mov    al,dh        ;восстанавливаем младшую и вывод
print_n:
    cmp    al,10
    sbb    al,69h
    das
    mov    dl,al
    mov    ah,2
    int    21h
    ret

massiv    dw    1,-2,3,4,5,6,7,11,9,10    ;задан произвольно с произвольным количеством
len    db    $-massiv
sign    dw    ?
max    dw    ?
ctrl    db    0Dh,0Ah,'$'
len1    db    0
massiv1:
end    start


Здесь сам файл.

Автор: seven65 12.12.2006, 01:06
Спасибо!!!

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)