Консультация № 184656
02.12.2011, 22:30
61.10 руб.
0 9 2
Уважаемые эксперты! Требуется решить следующую задачку на Assembler (TASM):
"В каждой пятерке массива а(15) найти второй по величине элемент, умножьте его на 2. Организовать массив b(3) из этих элементов".
Заранее спасибо!

Обсуждение

Неизвестный
03.12.2011, 11:02
общий
Надо понимать, что в скобках указано количество элементов массива?
И вы не указали размер элементов в массиве a?
Неизвестный
03.12.2011, 11:31
общий
1)да 2)на ваше усмотрение
Неизвестный
03.12.2011, 12:44
общий
это ответ
Здравствуйте, Sanek!
вот решение для 32х битных элементов массива a, в диапазоне от 0 до 2^31 для без знаковых элементов и от -2^30 до 2^30-1 для знаковых:

Приложение:
lea esi,[_massiv_a]
lea edi,[_massiv_b]

_find:
mov ecx,3
lodsd ;считываем первый элемент массива a
mov edx,eax ;записываем в edx
lodsd ;считываем второй элемент массива a
cmp eax,edx ;сравниваем с первым
jc @F ;если элементы без знака, для знаковых: jl @F
xchg eax,edx ;меняем местами, если второй меньше первого
@@: ;в edx больший из двух первых элементов
mov ebx,eax ;записываем в ebx меньший из двух первых элементов
_cikl_find:
lodsd ;считываем следующий элемент массива a
cmp eax,edx ;сравниваем с большим
jnc _loop_find ;если больше ищем дальше ;если элементы без знака, для знаковых: jnl @F
cmp eax,ebx ;сравниваем с меньшим
jnc @F ;если элементы без знака, для знаковых: jnl @F
xchg eax,ebx
@@: ;в ebx меньший элемент, в eax второй по величене
mov edx,eax ;зписываем второй по виличене элемент в edx
_loop_find:
loop _cikl_find ;повторяем поиск до 5-го элемента
shl edx,1 ;умножаем на 2 второй по величене элемент
mov eax,edx
stosd ;записываем умноженный на 2 второй по величене элемент
cmp edi,_massiv_b+3*4 ;проверяем количество записей масива b
jc _find ;если меньше трёх повторяем
ret ;выходим из создания масива b
Неизвестный
03.12.2011, 12:56
общий
03.12.2011, 12:57
ошибочка: ... в диапазоне от 0 до 2^31-1 для без знаковых элементов ...

давно
Посетитель
7438
7205
03.12.2011, 23:27
общий
это ответ
Здравствуйте, Sanek!
Вот Вам полностью функциональная 16-битная программа со вводом и выводом.

[code h=207];В каждой пятерке массива а(15) найти второй по величине элемент,
;умножьте его на 2. Организовать массив b(3) из этих элементов

code segment 'code' ;начало сегмента кода
assume cs:code,ds:data,ss:stk

main proc
mov ax, data
mov ds, ax
mov es, ax

Input:
call InputA ;вводим массив А
jz ToFormB ;проверим размер числа
lea dx, sNumError ;число превысило 32767
mov ah, 9
int 21h
jmp Input ;на повтор ввода

ToFormB:
call FormB ;формируем В
call OutputB ;выводим В

PrintAny:
lea dx, sAny ;press any key
mov ah, 9
int 21h

mov ah, 0
int 16h ;ждем any key

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

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

lea di, A ;адрес А
lea bp, [di+15*2] ;адрес за массивом (для контроля конца)
IA_ask:
lea dx, sNum ;приглашаем ко вводу
mov ah, 0ah
int 21h
lea si, sBuf ;строка с числами, разделенная разделителями
cld
IA_next:
cmp di, bp ;массив заполнен?
je IA_ok

call stoi ;[si] в число

jc IA_err ;ошибка разрядности?
jcxz IA_newrow ;дошли до конца строки?
stosw ;сохраняем
jmp IA_next ;на следующее число в строке
IA_newrow:
mov ah, 2
mov dl, 0ah
int 21h ;переход на новую строку
jmp IA_ask ;на запрос новой строки
IA_err:
or ax, 1 ;FZ == 0 -> ошибка размерности
IA_ok:
ret ;FZ == 1 -> все ок
InputA endp

FormB proc ;формируем массив В
lea si, A
lea di, B
mov cx, 3 ;3 пятерки
GroupsLoop:
push cx
mov cx, 5 ;число элементов в группе
xor dx, dx ;максимальное
xor bx, bx ;"предмаксимальное"
OneGroupLoop:
lodsw
cmp ax, bx ;сравним с предмаксимальным
jbe OneGroupNext ;<= - идем дальше
cmp ax, dx ;сравним с максимальным
je OneGroupNext ;одинаковые пропускаем
jb SetPrev ;меньше - сохраняем, как новый предмаксимальный
mov bx, dx ;больше - старый максимальный, как предмаксимальный
mov dx, ax ;новый, как новый максимальный
jmp OneGroupNext
SetPrev:
mov bx, ax ;новый предмаксимальный
OneGroupNext:
loop OneGroupLoop
mov ax,bx ;предмаксимальный
shl ax, 1 ;умножаем на 2
stosw ;сохраняем
pop cx
loop GroupsLoop
ret
FormB endp

OutputB proc ;выводим В
lea dx, sResult
mov ah, 9
int 21h ;вывод заголовока из dx
xor cx, cx ;счетчик элементов
OB_loop:
lodsw ;очередное значение
call itoa ;вывод числовой строки
inc cx ;считаем
cmp cx, 3 ;вывели 3?
je OB_ret
mov dl, ',' ;разделим запятой
int 21h ;ah = 2
jmp OB_loop
OB_ret:
ret
OutputB endp

itoa proc ;вывод беззнакового числа из ax
push cx ;сохраним счетчик колонок
mov bx, 10 ;будем делить на 10
xor cx, cx ;счетчик цифр
DivLoop:
xor dx, dx ;готовимся к делению dx:ax / bx
div bx ;ax - частное, dx - остаток=очередной младшей цифре
push dx ;сохраним цифру в стеке
inc cx ;посчитаем
test ax, ax ;продолжим, пока не 0
jnz DivLoop
mov ah, 2 ;функция вывода
PrintLoop: ;будем выводить в обратном порядке, начиная со старшей шифры
pop dx ;восстановим очередной разряд
or dl, '0' ;превратим в символ
int 21h ;выведем
loop PrintLoop
pop cx ;восстановим счетчик элементов
ret
itoa endp

stoi proc ;преобразование строки [si] в число AX
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
test dx, dx
pop dx ;новый
jnz stoi_err
test ax, ax
js stoi_err
and dx, 0fh ;'0'-'9' -> 0-9
add ax, dx ;добавляем новый разряд
js stoi_err
mov bx, ax ;сохраняем
inc cx ;считаем
jmp stoi_next ;продолжаем
stoi_sep: ;встретили разделитель
jcxz stoi_next ;были только разделители - на продолжение
; иначе - конец числа и выходим
stoi_eol: ; если числа нет и встретили 0dh - конец строки
mov ax, bx ;число возвращаем в ax
dec si ;шаг назад, чтобы легче было проанализировать 0dh
clc
ret
stoi_err:
stc
ret
stoi endp

code ends

data segment
sEnterA db 'Enter A (15 numbers): $'
sResult db 0dh,0ah,'B = $'
sNumError db 0dh,0ah,'Numbers must be < 32768',0dh,0ah,'$'
sAny db 0dh,0ah,'Press any key$',0

sNum db 80
len db ?
sBuf db 80 dup (?)

A dw 15 dup (?)
B dw 3 dup (?)
data ends

stk segment stack
dw 100h dup (?)
stk ends

end main
[/code]
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Посетитель
7438
7205
03.12.2011, 23:39
общий
Ваш фрагмент работает неправильно.
Только что проверил - задал данные:
5 5 2 1 3 1 1 1 1 1 5 3 2 1 7
Получил:
4 2 4
Т.е. нашлись числа 2, 1 и 2. А должны быть: 3, 1 и 5
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
04.12.2011, 00:18
общий
Адресаты:
Цитата: 359057
.. второй по величине элемент ...


в вашем примере это 2,1,2 причом тут 3,1,5 ?
давно
Посетитель
7438
7205
04.12.2011, 00:42
общий
Хм, я понял... Вы искали второго снизу, а я второго сверху
Спросим автора, что именно требуется...
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
05.12.2011, 22:29
общий
Уважаемые эксперты, спасибо Вам за оба решения!
Форма ответа