Консультация № 181128
06.12.2010, 17:55
53.34 руб.
0 8 1
Здравствуйте, уважаемые эксперты! Прошу Вас ответить на следующий вопрос:
Версию доса и тасма незнаю модель вроде small

В массиве а(10) отсортировать все элементы по возростанию до первого кратного 7

прошу сделать как можно проще, и желательно описание к каждой строчке чтобы было как можно понятнее
заранее благодарен

Обсуждение

давно
Посетитель
7438
7205
06.12.2010, 18:10
общий
Мало информации... Уточните:
1) Числа - байты, слова, двойные слова, знаковые/ беззнаковые?
2) Как задаем? Просто в сегменте данных, вводим с консоли, может - читаем с файла?
3) вывод на экран делаем/не делаем?
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Посетитель
7438
7205
07.12.2010, 02:25
общий
это ответ
Здравствуйте, Евтеев Алексей Николаевич!
Массив вводим с консоли. Причем, можно вводить, как в одно строке, так и в нескольких
Затем ищем число элементов до первого кратного 7 методом деления на 7 и сравнения остатка с 0.
Затем сортируем найденное количество методом пузырька (надеюсь, знакомы?).
Ну и, наконец, выводим все элементы на экран.
[code H=200];В массиве а(10) отсортировать все элементы по возростанию до первого кратного 7
.model small
.data
sEnter db 'Enter 10 numbers: ',0dh,'$'
sTitle db 0ah,'Sorted array: $'
.data?
a dw 10 dup (?)
len_a equ ($-a)/2 ;число элементов
;буфер для приема строки
sNum db ? ;максимальный размер буфера
sCount db ? ;реальный размер строки
sBuf db 80 dup (?) ;сама строка


.code
.286
assume ds:_DATA, es:_DATA, cs:_TEXT
start:
mov ax, _DATA
mov ds, ax
mov es, ax

push offset a ;параметром - адрес массива
call GetArray ;вводим массив

;найдем число элементов до первого кратного 7
lea si, a ;адрес массива
mov cx, len_a ;всего элементов
xor bx, bx ;искомый счетчик
mov di, 7 ;делим на 7
search_div7:
lodsw ;очередной элемент
cwd ;подготовим dx:ax к делению
idiv di ;ds:ax / 7
test dx, dx ;остаток есть?
jz sort ;нет - разделилось нацело, идем на сортировку
inc bx ;считаем
loop search_div7

;отсортируем bx элементов методом пузырька
sort:
mov cx, bx ;число сортируемых элементов
cmp cx, 2 ;0 и 1 нет смысла сортировать
jb print
dec cx ;число сравнений
lea si, a ;адрес элемента в массиве
SortLoop: ;цикл по поиску очередного минимального
lea di, [si+2] ;начинаем со следующего
push cx ;сохраним счетчик
mov ax, [si] ;текущий минимальный по адресу [si]
SearchMinLoop: ;цикл по всем последующим
;сравниваем текущий со всеми последующими
cmp ax, [di] ;если текущий минимальный <= последующего,
jle SortNext ; то обходим обмен
;меняем местами элементы
xchg ax, [di]
mov [si], ax ;по адресу [si] и в ax новый минимальный
SortNext:
inc di
inc di ;на следующий последующий
loop SearchMinLoop
inc si
inc si ;на следующий текущий
pop cx ;восстановим счетчик сравнений
loop SortLoop

print: ;выведем все элементы
lea dx, sTitle
mov ah, 9
int 21h ;заголовок

mov cx, len_a ;число всех
lea si, a ;адрес
PutLoop:
lodsw ;элемент
call PutNumber ;выводим
loop PutLoop

mov ah, 0
int 16h ;ждем нажатие на клавишу

mov ax, 4c00h ;выход в ДОС
int 21h

PutNumber proc ;преобразование числа из ax в строку и вывод на экран
push cx bx ;сохраним использованые регистры
xor cx, cx ;счетчик разрядов
mov bx, 10 ;делим на 10
DivLoop: ;цикл преобразования в разряды
cwd ;подготавливаем dx:ax к делению
idiv bx ;dx = очередному младшему разряду
push dx ;сохраним в стеке
inc cx ;считаем
test ax, ax ;продолжаем, пока не дойдем до 0
jnz DivLoop
PrLoop: ;цикл вывода в обратном порядке
pop ax ;берем число 0-9 из стека
or al, '0' ;преобразовываем в символ '0'-'9'
int 29h ;выводим
loop PrLoop
mov al, ' '
int 29h ;отделим пробелом
pop bx cx
ret
PutNumber endp

GetArray proc pArray:word ;ввод массива
local pLast:word ;переменная для сравнения на конец

push bp
mov bp, sp ;адресуем параметр через [bp+4]
sub sp, 2 ;2 байта под локальную переменную pLast

lea dx, sEnter
mov ah, 9
int 21h ;приглашение на ввод элементов массива

mov di, pArray ;адрес массива

mov ax, len_a ;адрес за массивом (для контроля конца)
shl ax, 1
add ax, pArray
mov pLast, ax ;сохраним
GA_ask:
mov ah, 2
mov dl, 0ah
int 21h ;переход на новую строку

mov sNum, 80
lea dx, sNum
mov ah, 0ah
int 21h
lea si, sBuf ;строка с числами, разделенная разделителями

GA_next:
cmp di, pLast ;массив заполнен?
je GA_ret

call stoi ;[si] -> ax
jcxz GA_ask ;дошли до конца строки?
stosw ;сохраняем
jmp GA_next ;на следующее число в строке
GA_ret:
mov sp, bp ;восстановим вершину стека
pop bp ;восстановим старое значение bp
ret 2 ;2выкинем" из стека параметр
GetArray endp

;функция преобразовывает числовую строку в число
;преобразование заканчивается по любому разделителю или концу строки (0dh)
;признаком конца строки является cx = 0
stoi proc ;преобразование строки [si] в беззнаковое число AX
push dx
xor bx, bx ;здесь будем стоить число
xor cx, cx ;счетчик разрядов
stoi_next:
lodsb ;очередной символ
cmp al, 0dh ;конец стоки?
je stoi_eol
cmp al, '0'
jb stoi_sep ;любая нецифра - разделитель
cmp al, '9'
ja stoi_sep
push ax ;сохраним новый разряд
mov ax, 10
mul bx ;умножим старшие на 10
pop dx ;новый
and dx, 0fh ;'0'-'9' -> 0-9
add ax, dx ;добавляем новый разряд
mov bx, ax ;сохраняем
inc cx ;считаем
jmp stoi_next ;продолжаем
stoi_sep: ;встретили разделитель
jcxz stoi_next ;были только разделители - на продолжение
; иначе - конец числа и выходим
stoi_eol: ; если числа нет и встретили 0dh - конец строки
mov ax, bx ;число возвращаем в ax
dec si ;шаг назад, чтобы легче было проанализировать 0dh
pop dx
ret
stoi endp

end start[/code]
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
07.12.2010, 11:19
общий
числа, залаем с консоли, вывод на экран делаем.... вроде так а можно без .startup.... а то мы вроде как такого не проходили
давно
Посетитель
7438
7205
07.12.2010, 11:30
общий
Что же Вы так неуверенно, "вроде", "вроде так"... Сами не знаете, что требуется?
Четко поставленная и понятая задача - половина успеха
Хм, а каков формат чисел, ответа так и дали... Будем считать, что беззнаковые слова. Или знаковые?
Ок, ввод с консоли и "без .startup" добавлю/переделаю чуть позже... Долго молчали, я уже и ответить успел...
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Посетитель
7438
7205
07.12.2010, 17:04
общий
Подправил
Кода добавилось. Помнится, Вы просили попроще...
Разбирайтесь. "Тяжело в ученьи, легко в бою" (с) Суворов
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
07.12.2010, 20:41
общий
вроде как безнаковые
Неизвестный
07.12.2010, 20:51
общий
а что такое .286
assume ds:_DATA, es:_DATA, cs:_TEXT, .data?, dw, equ, ($-a)/2, xchg, test, sub, shl, mul ?
а у нас за место _DATA @DATA пишут какая разница?
давно
Посетитель
7438
7205
07.12.2010, 22:40
общий
1) .186, .286, .386, .486, .586 и т.п. - команды для указания разрешенных команд.
Полагаю, что Вы в курсе, что у каждого нового поколения процессоров добавились команды.
В данном случае, я указал .286, чтобы было возможно использовать push <число>, впрочем ,достаточно было и .186

2) Кстати, да, лучше использовать @DATA. Почему? Сейчас объясню.
Объявление .data приводит к организации сегмента с именем _DATA (инициированные данные - данные будут в коде программы)
Объявление .data? приводит к организации сегмента с именем _BSS (неинициированные данные - данных в коде нет!)
Кроме того, эти два сегмента объединяются в группу с именем @DATA
И чтобы можно было адресовать оба сегмента, лучше использовать имя @DATA

3) команда ASSUME указывает ассемблеру, с какими сегментами связаны сегментные регистры.

4) _TEXT - имя сегмента кода

5) dw - резервирование слова (data word) или два байта в памяти
еще есть db (data byte), dd (data double word) и другие...

6) equ - от слова equivalent, т.е. эквивалент
Используется, чтобы дать имя какому-либо числу. Например, num equ 10

7) ($-a)/2 Тут надо уяснить несколько моментов:
а) $ в данном случае обозначает текущий адрес
б) $-a - разность в байтах между текущим адресом и адресом a
в) ($-a)/2 - разделив на 2, получаем число слов
г) len_a equ ($-a)/2 - len_a - это, фактически, константа, равная числу слов

8) xchg, test, sub, shl, mul - у-у-у, как все запущено.... Команды асссемблера надо знать...
В двух словах:
xchg - обмен содержимым операндов,
test - фактически and, но без смены содержимого операнда, только воздействие на флаги
sub - вычитание
shl - сдвиг влево на указанное число бит
mul - умножить аккумулятор на указанный операнд

Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Форма ответа