У меня задание, где нужно ввести массив и вывести его на экран. Но теперь пеподу понадобилось, чтоб еще найти максимальный элемент и заменить его на 1 и вывести на экран массив с замененным элементом. Я ввод/вывод еле сделал (и то не без дорых людей). Я как найти и заменить вообще не знаю.
Все время с++ изучали, а тут вот и ассемблер теперь нужно.
Помогите пожалуйста, если можете.
MODEL SMALL ;Малая модель памяти cs<>ds,cs<>ss
STACK 100h ;100h памяти под сегмент
LOCALS @@ ;Метки с префиксом @@ счит. локальными
mSize equ 3 ;Размер матрицы
;--------------------------------------------------
; Сегмент данных
;--------------------------------------------------
data segment ;Начало сегмента данных
matrix db mSize*mSize dup(?)
prompt2 db 'Массив:','$' ;DOS-строка 'числа...'
prompt3 db 'Введите число:','$' ;DOS-строка 'введите...'
endl db 13,10,'$' ;DOS-строка - перевод на след. строчку
nbSize db ? ;Заголовок под буфер ввода
nbInp db ?
buf db 6 dup(?) ;DOS-строка буфер для числа
db '$'
data ends ;Конец сегмента данных
;--------------------------------------------------
; Сегмент кода
;--------------------------------------------------
code segment ;Начало сегмента
assume cs:code,ds:data ;Обещаем выставить cs=code,ds=data
start: ;Точка входа в программу
mov ax,data ;ds=data (Инициализируем DS сегмент)
mov ds,ax
mov cx,mSize*mSize ;cx=кол-ву эл-тов матрицы
mov si,OFFSET matrix ;ds:si указывает на матрицу
call doEnterMatrix ;Вызываем процедуру заполнения матрицы
call doClearScreen ;Очищаем экран
mov si,OFFSET matrix ;ds:si указывает на матрицу
mov cx,mSize*mSize ;cx = кол-ву элементов в матрице
;Вызываем вывод перевода строки
mov si,OFFSET prompt2 ;ds:si указывает на prompt2
call doPrintStr ;Печатаем на экране строку prompt2
mov cx,mSize*mSize ;cx = кол-ву элементов в матрице
mov si,OFFSET matrix ;ds:si теперь указывает на матрицу
call doOut ;Вызываем вывод матрицы
mov si,OFFSET endl ;ds:si указывает на симв. перев. строки
call doPrintStr ;Вызываем вывод перевода строки
call doWaitAKey ;Ожидаем нажатие клавиши
mov ax,4C00h ;Выходим из программы -
int 21h ; прерывание 21h(DOS),ф-я 4Ch
;--------------------------------------------------
; doEnterMatrix - процедура ввода
;--------------------------------------------------
;
doEnterMatrix proc near ;Начало описания процедуры
push es ;Сохраняем es в стеке
push di ;Сохраняем di в стеке
push si ;Сохраняем si в стеке
push cx ;Сохраняем cx в стеке
push ax ;Сохраняем ax в стеке
pushf ;Сохраняем флаги в стеке
mov byte ptr ds:[nbSize],5 ;Макс. кол-во символов, кот.можно ввести
mov ax,ds ;ax=ds
mov es,ax ;es=ax=ds
mov di,si ;si=di
cld ;Сбрасываем флаг направления (вперёд)
@@lAgain: ;Начало цикла
call doClearScreen ;Вызываем очистку экрана
mov si,OFFSET prompt3 ;ds:si указывает на строку prompt3
call doPrintStr ;Вызываем проц. вывода строки на экран
mov ah,0Ah ;ah=0Ah
mov dx,OFFSET nbSize ;ds:dx указывает на буфер для ввода
int 21h ;Прерывание 21h(DOS) ввод строки
push cx ;Сохраняем cx в стеке
xor ch,ch ;ch=0 (быстрое обнуление)
mov cl,byte ptr ds:[nbInp] ;cl=кол-ву введённых символов
mov si,OFFSET buf ;ds:si указывает на буфер ввода
call doStr2Byte ;Вызвать преобразование строки в число
pop cx ;Восстановить cx из стека
cld ;Сбрасываем флаг направления(вперёд)
stosb ;Сохраняем полученное число в матрицу
loop @@lAgain ;Конец цикла
popf ;Восстанавливаем флаги из стека
pop ax ;Восстанавливаем ax из стека
pop cx ;Восстанавливаем cx из стека
pop si ;Восстанавливаем si из стека
pop di ;Восстанавливаем di из стека
pop es ;Восстанавливаем es из стека
ret ;Выходим из процедуры
doEnterMatrix endp ;Конец описания процедуры
;--------------------------------------------------
; doEnterMatrix - процедура вывода
;--------------------------------------------------
doOut proc near ;Начало описания процедуры
push si ;Сохраняем si в стеке
push dx ;Сохраняем dx в стеке
push cx ;Сохраняем cx в стеке
push bx ;Сохраняем bx в стеке
push ax ;Сохраняем ax в стеке
pushf ;Сохраняем флаги в стеке
xor ah,ah ;ah=0 (верхняя часть ax)
cld ;Сбрасываем флаг направления (вперёд)
@@lNext: ;Начало цикла
lodsb ;al=следующему эл-ту матрицы
mov bx,si ;Сохраняем si в bx (bx=si)
mov dx,cx ;Сохраняем cx в dx (dx=cx)
mov cx,LENGTH buf ;cx = размеру буфера
mov si,OFFSET buf ;ds:si указывает на начало буфера
call doWord2Str ;Вызываем преобразование числа в строку
mov cx,dx ;Восстанавливаем cx из dx (cx=dx)
mov si,OFFSET buf ;ds:si указывает на буфер (строку)
call doPrintStr ;Выводим буфер (строку)(число)
mov si,bx ;Восстанавливаем si из bx (si=bx)
@@lSkip: ;Метка @@lSkip
loop @@lNext ;Конец цикла
popf ;Восстанавливаем из стека флаги
pop ax ;Восстанавливаем из стека ax
pop bx ;Восстанавливаем из стека bx
pop cx ;Восстанавливаем из стека cx
pop dx ;Восстанавливаем из стека dx
pop si ;Восстанавливаем из стека si
ret ;Выходим из процедуры
doOut endp ;Конец описания процедуры
;--------------------------------------------------
; doClearScreen - процедура очистки экрана
;--------------------------------------------------
doClearScreen proc near ;Начало описания процедуры
push ax ;Сохраняем ax в стеке
pushf ;Сохраняем флаги
mov ax,0003h ;ah = 0, al = 03 (номер видео режима)
int 10h ;Прерыване 10h(BIOS) устан. вид.режима
popf ;Восстанавливаем из стека флаги
pop ax ;Восстанавливаем из стека ax
ret ;Выходим из процедуры
doClearScreen endp ;Конец описания процедуры
;--------------------------------------------------
; doWaitAKey - процедура ожидания клавиши
;--------------------------------------------------
doWaitAKey proc near ;Начало описания процедуры
push ax ;Сохраняем ax в стеке
pushf ;Сохраняем флаги в стеке
xor ah,ah ;ah=0 (быстрое обнуление)
int 16h ;Прерывание 16h(BIOS) читаем клавишу
popf ;Восстанавливаем из стека флаги
pop ax ;Восстанавливаем из стека ax
doWaitAKey endp ;Конец описания процедуры
;--------------------------------------------------
; doPrintStr - Вывод DOS строки на экран
;--------------------------------------------------
doPrintStr proc near ;Начало описания процедуры
push dx ;Сохраняем dx в стеке
push ax ;Сохраняем ax в стеке
pushf ;Сохраняем флаги в стеке
mov ah,09h ;ah = 09h
mov dx,si ;dx = si
int 21h ;Прерывание 21h(DOS) выв. строки
popf ;Восстанавливаем из стека флаги
pop ax ;Восстанавливаем из стека ax
pop dx ;Восстанавливаем из стека dx
ret ;Выходим из процедуры
doPrintStr endp ;Конец описания процедуры
;--------------------------------------------------
; doWord2Str - Перевод числа в строку
;--------------------------------------------------
doWord2Str proc near ;Начало описания процедуры
push si ;Сохраняем si в стеке
push dx ;Сохраняем dx в стеке
push cx ;Сохраняем cx в стеке
push bx ;Сохраняем bx в стеке
push ax ;Сохраняем ax в стеке
pushf ;Сохраняем в стеке флаги
mov dl,al ;Сохраняем al в dl (dl=al)
mov al,' ' ;al = пробелу
call doFillBuf ;Заполняем буфер пробелами
mov al,dl ;Восстанавливаем al (al=dl)
test ah,10000000b ;ax<0? (первый бит установлен?)
jz @@skipNeg ;Нет => @@skipNeg
neg ax ;ax=-ax
mov byte ptr ds:[si],'-' ;Записываем в буфер симв. '-'
@@skipNeg:
dec cx ;Уменьшаем cx (место под знак)
add si,cx ;ds:si указывает на конец буфера
mov bx,10 ;bx=10 (будем делить на 10)
@@lNext: ;Начало цикла
xor dx,dx ;Обнуляем остаток от деления (dx=0)
div bx ;Делим ax на bx (ax=ax/10, dx=остаток)
add dl,'0' ;Прибавляем к dl символ '0'
mov byte ptr ds:[si],dl ;Сохраняем в буфере
test ax,ax ;ax = 0? (делить имеет смысл?)
jz @@lExit ;нет => выход из цикла
dec si ;Сдвигаемся по буферу
loop @@lNext ;Следующий шаг
@@lExit:
popf ;Восстанавливаем из стека флаги
pop ax ;Восстанавливаем из стека ax
pop bx ;Восстанавливаем из стека bx
pop cx ;Восстанавливаем из стека cx
pop dx ;Восстанавливаем из стека dx
pop si ;Восстанавливаем из стека si
ret ;Выходим из процедуры
doWord2Str endp ;Конец описания процедуры
;--------------------------------------------------
; doStr2Byte - Перевод строки в байт
;--------------------------------------------------
doStr2Byte proc near ;Начало описания процедуры
push si ;Сохраняем si в стеке
push dx ;Сохраняем dx в стеке
push cx ;Сохраняем cx в стеке
push bx ;Сохраняем bx в стеке
mov bx,cx ;Сохраняем cx в bx
cld ;Сбрасываем флаг направления(вперёд)
lodsb ;Читаем первый символ
cmp al,'-' ;Сравниваем его с символом '-'
jne @@lSkip ;Если не равен => lSkip
dec cx ;Иначе уменьшаем счётчик символов
dec bx ;И сохранённый тоже
@@lNext: ;Начало цикла (проверка строки)
lodsb ;Загружаем следующий символ в al
@@lSkip:
cmp al,'0' ;Сравниваем его с '0'
jb @@lExitE ;Если меньше,то выходим из цикла(ошибка)
cmp al,'9' ;Сравниваем его с '9'
ja @@lExitE ;Если больше,то выходим из цикла(ошибка)
loop @@lNext ;Конец цикла
dec si ;Передвигаем si на последний символ
mov cx,bx ;Восстанавливаем cx из bx
std ;Устанавливаем флаг переноса (назад)
mov dx,0A01h ;dh=10, dl=1 (коэфф.умножения, множит.)
xor bx,bx ;bx=0 (сумма - быстрое обнуление)
@@lNextD: ;Начало цикла
lodsb ;Считываем предыдущий символ
sub al,'0' ;Преобразуем символ в число
mul dl ;Умножаем его на dl (1,10,100...)
test ah,ah ;Проверяем вышел ли он за пределы байта
jnz @@lExitE ;Если вышел - выходим из цикла (ошибка)
add bx,ax ;bx=bx+ax (суммируем)
mov al,dl ;al=dl (готовимся к умножению множителя=)
mul dh ;умножаем
mov dl,al ;dl=множителю (1,10,100...)
loop @@lNextD ;Конец цикла
lodsb ;Дочитываем символ
cmp al,'-' ;Сравниваем его с '-'
jne @@lSkipN ;Если нет =>lSkipN
neg bx ;Иначе bx=-bx
@@lSkipN:
mov ax,bx ;ax=bx=числу
clc ;Сбрасываем флаг переноса (нет ошибки)
jmp @@lExit ;Выходим
@@lExitE:
stc ;Устанавливаем флаг переноса(ошибка)
@@lExit:
pop bx ;Восстанавливаем из стека bx
pop cx ;Восстанавливаем из стека cx
pop dx ;Восстанавливаем из стека dx
pop si ;Восстанавливаем из стека si
ret ;Выходим из процедуры
doStr2Byte endp ;Конец описания процедуры
;--------------------------------------------------
; doFillBuf - Заполняет буфер заданным значением
;--------------------------------------------------
doFillBuf proc near ;Начало описания процедуры
push es ;Сохраняем es в стеке
push di ;Сохраняем di в стеке
push cx ;Сохраняем сx в стеке
push bx ;Сохраняем bx в стеке
mov bx,ds ;bx = ds
mov es,bx ;es = bx = ds
mov di,si ;di = si
cld ;Сбрасываем флаг направления (вперёд)
rep stosb ;Пишем сод. ax, cx раз в строку es:di
pop bx ;Восстанавливаем из стека bx
pop cx ;Восстанавливаем из стека cx
pop di ;Восстанавливаем из стека di
pop es ;Восстанавливаем из стека es
ret ;Выходим из процедуры
doFillBuf endp ;Конец описания процедуры
code ends ;Конец сегмента кода
end start ;Конец программы