Модераторы: Poseidon
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> [Assembler] Ввод-вывод и арифметическая обработка, Разбить входные числа на массив 
V
    Опции темы
denura
Дата 7.5.2009, 07:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 13.11.2008

Репутация: нет
Всего: нет



Помогите, пожалуйста, написать такую программу:

ТЕМА: Ввод-вывод и арифметическая обработка числовых данных"

ЗАДАНИЕ: Написать программу, выполняющую
- ввод массива целыx многозначныx чисел со знаком. При вводе осуществляется контроль допустимости вводимыx символов. Ввод предваряется текстовым приглашением.
- арифметическую и логическую обработку массива чисел по заданию, приведенному ниже.
- преобразование числового результата в ASCII-строку и отображение на дисплее.

Вычисляемое значение задается номером оператора n и номером условия m, определяющего операнды, в виде пары чисел (n,m).

Собственно, сама задача:
Разбить входные числа на массив положительных и массив отрицательных чисел, вычислить попаpные пpоизведения и их сумму.

Не знаю даже, с чего начать. Знаю только, что потребуются следующие функции:
Функции прерывания 21h DOS для ввода с клавиатуры и вывода на дисплей.
Функции прерывания 10h BIOS для вывода на дисплей.
Функции прерывания 16h BIOS для ввода с клавиатуры.

Описание работы программы:

    Массив будет содержать байты (или слова).
    Я ввел числа, увидел на экране, как они разбились на положительные и отрицательные, а, затем, жму "Вычислить произведение", - получаю результат и жму "Выхислить сумму" - примерно так.
    Когда пользователь не ввел отрицательных чисел, сказать ему об этом и пригласить к вводу.
    Складывать только отрицательные и положительные, соответственно и умножать, если нет пары, то не трогать это число, а просто вывести.
    Например, введен массив
1, -2, 3, -5, 4, 3
получили
1, 3, 4, 3
-2, -5

Складываем:
1 + (-2) = -1
3 + (-5) = -2
Остальное выводим не трогая:
4
3

Программа получается такая:
1. Ввод
2. Выбор действия
3. Вывод
4. Задержка на выход

Еще есть такие BSD числа, но они, вроде бы не удобны для использования в данной задаче.

Для компиляции и линковки программы желательно использовать tasm и tlink

Это сообщение отредактировал(а) denura - 8.5.2009, 09:17
PM MAIL   Вверх
airyashov
Дата 7.5.2009, 11:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 284
Регистрация: 1.7.2008

Репутация: 1
Всего: 6



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




--------------------
icq:3(один)7748666
mail:airyashov( а )inbox.ru
PM MAIL   Вверх
denura
Дата 22.5.2009, 17:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 13.11.2008

Репутация: нет
Всего: нет



Программа написана, но есть небольшие заковырки:
при возникновении переполнения при умножении не идет проверка флага OF и результат получается неверным. Потому его вычисление надо как-то запретить выводом текстового сообщения.
Еще хотелось бы выйти из программы, не вводя чисел.
Также при вводе неправильной конфигурации чисел совместно с правильной хотелось бы чтобы предыдущие введенные числа оставались и не приходилось их вводить заново
Вот код программы:
Код

;Разбить входные числа на массив положительных и массив отpицательных чисел, вычислить попаpные пpоизведения и их сумму.

COUNT    equ    16 ;EQU - одна из команд препроцессора. EQU присваивает ячейке символическое имя и позволяет работать в тексте программы с именем переменной
;объявляем переменную 'count'

d1    segment para public 'data'
mess1        db 'Enter numbers (For the input termination, press twice key "Enter"):',10,13,'$'
mess2        db 10,13,'Output array:',10,13,'$'
messNoPos    db 10,13,'Positive numbers are not entered! Please, repeat input',10,13,'$'
messNoNeg    db 10,13,'Negative numbers are not entered! Please, repeat input',10,13,'$'
messOper    db 10,13,'1. Calculate sum'    ;меню
        db 10,13,'2. Calculate mul'
        db 10,13,'3. Exit'
        db 10,13,'Your choice: $'
in_str        db 22 dup (?)        ;строка для ввода числа
pos_cnt        dw ?                ;количество положительных
neg_cnt        dw ?                ;количество отрицательных
positive    dw COUNT dup (?)    ;массив положительных (max COUNT)
negative    dw COUNT dup (?)    ;массив отрицательных (max COUNT)
d1 ends

st1    segment para stack 'stack'
    dw 100 dup (?)
st1    ends

c1    segment para public 'code'
assume    cs:c1,ds:d1,ss:st1
start:    mov    ax,d1
        mov    ds,ax
        mov    in_str,20        ;подготовим буфер ввода числа
repeat:
    mov    pos_cnt,0        ;обнулим счетчики
    mov    neg_cnt,0
        mov    dx,offset mess1    ;Приглашение ввода
        mov    ah,9            ;функция прерывания 21h DOS для вывода на экран строки символов
        int    21h    
    mov    cx,COUNT        ;вводим максимум COUNT чисел
input:
        mov    dx,offset in_str
        mov    ah,0ah            ;функция прерывания 21h DOS для ввода с клавиатуры строки символов
        int    21h
        cmp    in_str+1,0        ;по пустой строке заканчиваем ввод
    jz    comp_counts        ;проверим счетчики

    call    GetNum            ;преобразуем строку в число (в AX)
    jc    repeat            ;при ошибке на повтор ввода

    test    ax,ax            ;проверим знак числа
    js    save_negative
save_positive:
    mov    di,pos_cnt        ;счетчик положительных одновременно является индексом места, куда пишем
    shl    di,1            ;только умножим его на 2, чтобы адресовать слово
    mov    positive[di],ax        ;сохраняем
    inc    pos_cnt            ;инкремент количества положительных
    jmp    next_row        ;на перевод строки
save_negative:
    mov    di,neg_cnt        ;то же самое для отрицательных
    shl    di,1
    mov    negative[di],ax
    inc    neg_cnt
next_row:
    mov    al,0ah            ;перевод строки
    int    29h ;функция DOS вывода на экран — недокументированное прерывание 29h. Быстрый вывод символа на экран. В большинстве случаев INT 29h просто немедленно вызывает функцию BIOS «вывод символа на экран в режиме телетайпа», так что никаких преимуществ, кроме экономии байт при написании как можно более коротких программ, она не имеет.
    loop    input            ;повторим ввод чисел

comp_counts:
    cmp    pos_cnt,0        ;были ли введены положительные числа
    jne    comp_neg
    lea    dx,messNoPos        ;сообщение об ошибке (не были введены положительные числа)
    jmp    Message
comp_neg:
    cmp    neg_cnt,0        ;были ли введены отрицательные числа
    jne    output
    lea    dx,messNoNeg        ;сообщение об ошибке (не были введены отрицательные числа)
Message:
    mov    ah,9
    int    21h
    jmp    repeat            ;на повтор ввода

output:                    ;выведем введенные числа
    mov    dx,offset mess2 ;Вывод
        mov    ah,9 ; функция прерывания 21h DOS для вывода на экран строки символов
        int    21h

    mov    cx,pos_cnt        ;число положительных
    lea    si,positive        ;их адрес
    call    PrintNumbers

    mov    cx,neg_cnt        ;отрицательные
    lea    si,negative
    call    PrintNumbers

oper_loop:                ;вывем меню и отработаем операции
    mov    dx,offset messOper    ;Вывод
        mov    ah,9            ; функция прерывания 21h DOS для вывода на экран строки символов
        int    21h

    mov    ah,1            ;ввод кода клавиши с одновременным выводом на экран
        int    21h

    push    ax
    mov    al,0ah            ;перевод строки
    int    29h
    pop    ax
                    ;проанализируем код (в al)
    cmp    al,'3'            ;если 3, то выход
    je    exit
    cmp    al,'1'            ;если 1, то сумма
    je    summa
    cmp    al,'2'            ;если 2, то произведение
    jne    oper_loop        ;если что-то другое, то на повтор
    xor    bp,bp            ;признак произведения
    jmp    calc_oper
summa:
    mov    bp,1            ;признак суммы
calc_oper:
    mov    cx,pos_cnt        ;количество положительных
    mov    bx,neg_cnt        ;кол отрицательных
    lea    si,positive        ;адрес положительных
    lea    di,negative        ;адрес отрицательных
    cmp    cx,bx            ;найдем минимум
    jbe    next_oper
    xchg    cx,bx
    xchg    si,di
next_oper:                ;сначала отработаем общую часть
                    ;в CX минимум из наборов, в SI - его адрес!
    lodsw                ;загрузка (слова) в AX первого операнда
    test    bp,bp            ;код операции
    jz    mult
    add    ax,[di]
    jmp    print_oper
mult:
    imul    word ptr [di]        ;знаковое умножение
print_oper:
    add    di,2            ;сдвинем индекс второго операнда
    call    PrintNum        ;выведем
    cmp    bx,1            ;в случае одинаковых количеств обойдем вывод запятой
    je    print_last
    mov    al,','            ;разделительные запятая и пробел
    int    29h
    mov    al,' '
    int    29h
    dec    bx            ;уменьшим счетчик большего набора
    loop    next_oper
                    ;выведем остаток болшьшего набора
    mov    cx,bx            ;оставшееся количество в большем наборе
print_tail:
    mov    ax,[di]            ;значение
    add    di,2            ;сдвинем индекс
    call    PrintNum        ;выведем
    cmp    cx,1            ;обойдем вывод запятой после последнего числа
    je    Print_last
    mov    al,','            ;разделительные запятая и пробел
    int    29h
    mov    al,' '
    int    29h
    loop    print_tail

Print_last:                ;перевод строки
    mov    al,0dh
    int    29h
    mov    al,0ah
    int    29h
    jmp    oper_loop        ;перейти на вывод меню
exit:
        mov    ax,4c00h        ;выход
        int    21h
;
PrintNumbers    proc            ;вывод введенных чисел
PN_loop:
    lodsw                ;число
    call    PrintNum        ;вывод
    cmp    cx,1            ;обойдем вывод запятой после последнего числа
    je    PN_last
    mov    al,','
    int    29h
    mov    al,' '
    int    29h
    loop    PN_loop
PN_last:
    mov    al,0dh            ;перевод строки
    int    29h
    mov    al,0ah
    int    29h
    ret
PrintNumbers    endp

PrintNum    proc        ; вывод числа из AX
    push    bx cx
    test    ax, ax        ;проверим на знак
    jns    form_str    ;для положительного на вывод
    push    ax        ;для отрицательного выводим - и меняем знак
    mov    al,'-'        ;знак -
    int    29h
    pop    ax
    neg    ax        ;меняем знак числа на +, теперь оно положительное

form_str:
    mov    bx, 10        ; будем делить на 10
    xor    cx, cx        ; счетчик цифр
div_loop:            ; цикл получения десятичных разрядов
    xor    dx, dx        ; подготовимся для очередного деления
    div    bx        ; в dx остаток - очередной десятичный разряд
    push    dx        ; сохраним в стеке (от младшего к старшему)
    inc    cx        ; посчитаем
    test    ax, ax        ; есть еще десятичные разряды?
    jnz    div_loop    ; продолжим

pr_loop:            ; цикл вывода десятичных цифр-символов
    pop    ax        ; востановим очередной разряд (от старшего к младшему)
    add    al, '0'        ;  символ цифры
    int    29h        ; вывод
    loop    pr_loop        ; по всем цифрам
    pop    cx bx
    ret
PrintNum    endp
;
GetNum    proc            ; преобразование сроки в число
    push    cx
    xor    di, di        ; здесь будем накапливать число
    mov    cl, 0        ; флаг знака
    mov    ch, 0        ; количество цифр
    xor    bx, bx        ; очередной знак (для сложения со словом)
        mov    si,offset in_str+2 ;первый символ для обработки 
get_num_loop:
    lodsb            ; очередная цифра
; проверим на разделители
    cmp    al, 0dh
    je    num_end_found    ; конец ввода
    cmp    al, ' '
    je    num_end_found
    cmp    al, 9
    je    num_end_found
; минус может быть только один и в первой позиции!    
    cmp    al, '-'
    jne    cmp_num
    test    ch, ch        ; были ли введены цифры?
    jnz    set_c        ; были - ошибка - минус не в первой позиции!
    test    cl, cl        ; был ли уже введен минус?
    jnz    set_c        ; был - ошибка - можно только один!
    mov    cl, 1        ; пометим отрицательное число
    jmp    get_num_loop    ; на анализ следующего символа
cmp_num:
    cmp    al, '0'        ; цифра?
    jb    set_c        ; ошибка - не цифра!
    cmp    al, '9'
    ja    set_c

    inc    ch        ; считаем цифры
    and    al, 0fh        ; цифра -> число (30h-39h -> 0-9)
    mov    bl, al        ; сохраним (bh=0)
    mov    ax, 10        ; умножим на 10 
    imul    di        ; предыдущее значение
    test    dx, dx        ; больше cлова - ошибка!
    jnz    set_c
    add    ax, bx        ; добавим сохраненный разряд
    jc    set_c        ; больше  слова - ошибка!
    js    set_c        ; больше 32767 - ошибка!
    mov    di, ax        ; сохраним
    jmp    get_num_loop    ; идём на анализ следующего символа

num_end_found:            ; встретили разделитель
    test    ch, ch        ; что-то было?
    jz    set_c        ; не было числа (например, был введен один минус)
    test    cl, cl        ; число отрицательное?
    jz    get_num_ret
    neg    di        ; дополнительный код отрицательного числа
get_num_ret:
    mov    ax, di        ; результат в ax
    pop    cx
    clc            ; все ок. Команда clc сбрасывает флаг переноса CF в регистре флагов. Команда не имеет параметров и не воздействует на остальные флаги процессора.
    ret ; Возврат из процедуры, вызванной командой call
set_c:
    pop    cx
    stc            ; ошибка. Установка флага переноса CF в 1
    ret
GetNum    endp    

c1    ends

    end    start


Это сообщение отредактировал(а) denura - 22.5.2009, 17:58
PM MAIL   Вверх
denura
Дата 8.6.2009, 17:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 13.11.2008

Репутация: нет
Всего: нет



Вопрос решен
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Центр помощи"

ВНИМАНИЕ! Прежде чем создавать темы, или писать сообщения в данный раздел, ознакомьтесь, пожалуйста, с Правилами форума и конкретно этого раздела.
Несоблюдение правил может повлечь за собой самые строгие меры от закрытия/удаления темы до бана пользователя!


  • Название темы должно отражать её суть! (Не следует добавлять туда слова "помогите", "срочно" и т.п.)
  • При создании темы, первым делом в квадратных скобках укажите область, из которой исходит вопрос (язык, дисциплина, диплом). Пример: [C++].
  • В названии темы не нужно указывать происхождение задачи (например "школьная задача", "задача из учебника" и т.п.), не нужно указывать ее сложность ("простая задача", "легкий вопрос" и т.п.). Все это можно писать в тексте самой задачи.
  • Если Вы ошиблись при вводе названия темы, отправьте письмо любому из модераторов раздела (через личные сообщения или report).
  • Для подсветки кода пользуйтесь тегами [code][/code] (выделяйте код и нажимаете на кнопку "Код"). Не забывайте выбирать при этом соответствующий язык.
  • Помните: один топик - один вопрос!
  • В данном разделе запрещено поднимать темы, т.е. при отсутствии ответов на Ваш вопрос добавлять новые ответы к теме, тем самым поднимая тему на верх списка.
  • Если вы хотите, чтобы вашу проблему решили при помощи определенного алгоритма, то не забудьте описать его!
  • Если вопрос решён, то воспользуйтесь ссылкой "Пометить как решённый", которая находится под кнопками создания темы или специальным флажком при ответе.

Более подробно с правилами данного раздела Вы можете ознакомится в этой теме.

Если Вам помогли и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, Poseidon, Rodman

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Центр помощи | Следующая тема »


 




[ Время генерации скрипта: 0.0463 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.