Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Низкоуровневое программирование > Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 23.12.2010, 11:24   #1
SergSpectr
Новичок
Джуниор
 
Регистрация: 23.12.2010
Сообщений: 4
По умолчанию Контроль корректности ввода данных

Всем доброго времени суток.
Возникла проблема с лабораторной работой. При запуске exe программы, выводится только первое и последнее сообщение, а далее вылет проги. Не могли бы подсказать в чем может быть проблема??? Заранее спасибо за помощь

data segment para public 'data' ;сегмент данных

msg0 db 0ah,0dh,'(a*d)/(a+b) = $'
errmsg0 db 0ah,0dh,'Ошибка преобразования в целое$'
errmsg1 db 0ah,0dh,'Переполнение разрядной сетки$'
errmsg2 db 0ah,0dh,'Деление на ноль$'
errmsg3 db 0ah,0dh,'Дублированный или пустой параметр$'
errmsg4 db 0ah,0dh,'Ошибка параметров командной строки$'


var_a db 0
var_b db 0
var_d db 0
buf db 6 dup(' ')

data ends

stk segment stack 'stack'
db 256 dup ('?') ;сегмент стека
stk ends

code segment para public 'code' ;начало сегмента кода



;начало процедуры main
main proc
assume cs:code,dsata,ss:stk
mov ax,data ; адрес сегмента данных в регистр ax
mov ds,ax ; ax в ds
call clear_scr ;
lea dx, msg0
call write_str ;
call get_cmd_line ; В ES:SI Длина командной строки

; Обработка командной строки
xor cx,cx
mov cl, es:[si]
inc si
CICLE:
dec cx
mov dl, es:[si]
inc si

cmp dl,2fh ; Это символ '/' ?
jne SKIP_WAIT ; Нет, но это может быть пробел

mov dl, es:[si] ; Да, Это начало ключа
inc si ; Увеличим индекс
dec cx ; Уменьшим счетчик

; Проверка параметра /a
cmp dl,61h ; Это символ 'a' ?
jne PB ; Нет, проверим 'b'
test bl,01h ; Параметра /a уже считан ?
jnz PARAMerr ; Да это дубль
xor bl,01h ; Нет, установим признак параметра /a
lea dx,buf ;
call extract_key; Читает параметр в буфер
jz PARAMerr
call str_to_int ;
mov var_a,dl ;
jmp RETRY
; Проверка параметра /b
PB:
cmp dl,62h ; Это символ 'b' ?
jne PD ; Нет, проверим 'd'
test bl,02h ; Параметра /b уже считан ?
jnz PARAMerr ; Да это дубль
xor bl,02h ; Нет, установим признак параметра /b
lea dx,buf ;
call extract_key; Читает параметр в буфер
jz PARAMerr
call str_to_int ;
mov var_b,dl ;
jmp RETRY

; Проверка параметра /d
PD:
cmp dl,64h ; Это символ 'd' ?
jne UNKNOW ; Нет, неизвестный параметр
test bl,04h ; Параметра /d уже считан ?
jnz PARAMerr ; Да это дубль
xor bl,04h ; Нет, установим признак параметра /d
lea dx,buf ;
call extract_key; Читает параметр в буфер
jz PARAMerr
call str_to_int ;
mov var_d,dl ;
jmp RETRY

; Пропуск пробелов
SKIP_WAIT:
cmp dl,20h ; Это пробел ?
jne UNKNOW ; Нет это какой то левый символ
;
RETRY:
cmp cx,0h
jne CICLE

cmp bl,7 ; Проверим все ли параметры были найдены
jne UNKNOW ;

call calculate;
call write_result;
call dos_exit
UNKNOW:
lea dx,errmsg4
call write_str
call dos_exit

PARAMerr:
lea dx,errmsg3
call write_str
call dos_exit
main endp ;конец процедуры main
SergSpectr вне форума Ответить с цитированием
Старый 23.12.2010, 11:26   #2
SergSpectr
Новичок
Джуниор
 
Регистрация: 23.12.2010
Сообщений: 4
По умолчанию

; В ES:SI размер коммандной строки
; ES:SI+1 начало коммандной строки заканчивается 0Dh
get_cmd_line proc
push ax
push bx
mov ah,62h
int 21h
mov bx,80h
lea si,es:[bx]
pop bx
pop ax
ret
get_cmd_line endp


; Формирует подстроку из строки заканчивающейся 0dh разделитель ' ' и '/'
; [размер буфера][размер прочитанный].......[CR]
; Вход :
; es:si Индекс начала подстроки - параметра
; dsx адрес выходного буфера
; cx число необработанных символов командной строки (необяз)
; Выход
; si Индекс конца подстроки - параметра
; [dx+1] Длина подстроки - параметра
; cx Уменьшает число необработанных символов на длину строки (необяз)
; Устанавливает флаг 0 если строка 0 размера

extract_key proc
push ax
push bx
push dx
push bp

mov bx,dx
mov bp,dx;

xor dx,dx
add bx,2
SPUSH:
mov dl,es:[si]
cmp dl,0dh ; Если ентер то конец обрботки
je FPUSH
cmp dl,2fh ; Если слэш то конец обрботки
je FPUSH
cmp dl,20h ; Если пробел то конец обрботки
je FPUSH
; Иначе перйдем к следующему символу подстроки
mov ds:[bx],dl
inc bx ;
inc si ;
jmp SPUSH
FPUSH:
mov al,0dh
mov ds:[bx],al
sub bx,bp ;
sub bx,2
mov ds:[bp+1],bl ;
sub cx,bx ;
cmp bl,00h ; Установим флаг нуля
pop bp
pop dx
pop bx
pop ax
ret
extract_key endp


; Число загружено в Al
; Перевод Числа в строку загруженную в DS:DX
Int_To_Str proc near
push ax
push bx
push cx
push dx
push bp


xor cx,cx ; Счетчик записанных в стек симолов
mov bp,dx ; Адрес строки занесем в Bp
xor dx,dx
mov bl,10 ; Показатель СС = 10

cmp al,0h
jg PUSHASCII
jz PUSHASCII

neg al
mov[bp],2dh
inc bp

PUSHASCII:
cbw ;
xor ah,ah
div bl ; После деления в Al целая часть, В Ah - остаток
add ah,30h ; Получили ASCII символ цифры остатка в ah
mov dl,ah
push dx ; Затолкнем ASCII символ в стек
inc cl ; Увеличим счетчик записанных в стек символов
cmp al,0 ; Пока частное <> 0
jnz PUSHASCII ; выполняем деление (перевод в 10 cc)

; Вытолкнем все ASCII из стека в строку
POPASCII:
pop dx ; выпихнем ASCII код из стека (В обратном порядке)
mov [bp],dl ; Занесем символ в строку
inc bp ;
loop POPASCII ;

mov [bp],24h ; Завершающий символ в строке $

pop bp
pop dx
pop cx
pop bx
pop ax
ret
Int_To_Str endp


; Производит вычисление (d*a)/(a+b) результат в Dx
; Dl-частное Dh-Остаток
calculate proc near
push ax
push bx
push cx

xor ax,ax
mov al,var_a ; Занесем множитель в Ax
imul var_d ; (a*d)=>Dx (Результат умножения слово)
; В Ax делимое размер слово ()

; (a+b) Получили делитель в Bl
mov Bl,var_a ;
add Bl,var_b ;
jo OVERFLOW ;
jz DEVIDE_BZ ;

; Выполним деление (Ax / Bl)
call devide ;

; частное в Ax, остаток в Dx
; Проверим частное
cmp ax,-128 ;
jl OVERFLOW
cmp ax,127 ;
jg OVERFLOW

; Сделаем остаток положительным
cmp dx,0
jg FINISH
neg dx
jmp FINISH
OVERFLOW:
call cr
lea dx, errmsg1
call write_str
call dos_exit
DEVIDE_BZ:
call cr
lea dx, errmsg2
call write_str
call dos_exit
FINISH:
mov Dh,Dl ; Сохраним результат Dh-остаток (Уже больше 0)
mov Dl,Al ; Dl-частное
pop cx
pop bx
pop ax
ret
calculate endp
SergSpectr вне форума Ответить с цитированием
Старый 23.12.2010, 11:27   #3
SergSpectr
Новичок
Джуниор
 
Регистрация: 23.12.2010
Сообщений: 4
По умолчанию

; Деление Ax/Bl Частное в Ax Остаток в Dx
devide proc
push bx
cwd ; Расширим делимое в AX до 2го слова DX:AX
push ax
mov al,bl
cbw ; Расширим делитель до слова
mov bx,ax ;
pop ax
; Делимое в DX:AX Делитель в BX
idiv bx
; Частное в Ax остаток в DX
pop bx
ret
devide endp


; Вывод результата деления
write_result proc
push ax
push dx
call cr ; перевод строки
; Вывод Частного
xor ax,ax
push dx
mov al,dl;
lea dx,buf;
call int_to_str;
call write_str; ;

call dot ;

; Вывод остатка
xor ax,ax
pop dx
mov al,dh;
lea dx,buf;
call int_to_str;
call write_str; ;
pop dx
pop ax
ret
write_result endp




; СТРОКА в DS:DX
; Переводит текстовую строку в число со знаком размером байт
; возврат в DOS при переполнении разрядной сетки и недопустимых символах в
; строке (допустимы символы - + 0..9 в естественном порядке следования)
; Вызывает GOTO_XY, WRITE_STR,

str_to_int proc near
push ax
push bx
push cx
push bp
push si
xor bx,bx
xor cx,cx ; Обнулим регистр счетчика
mov bp,dx ; Занесем адрес строки в Bp
xor dx,dx ; Через этот регистр возвратим значение
mov si,0 ; Знак по умолчанию +
mov bl,0 ; Промежуточное хранение результата
inc bp ; Спозиционируем на число прочитанных символов
mov cl,[bp] ; Занескм в Cl число прочитанных символов
inc bp ; Позиционируем индекс на 1й символ в строке
mov dl,[bp] ; Посмотрим 1 символ (Проверим знак ли это ?)
cmp dl,2dh ; Это '-' ?
jne PLUS ; Нет это не '-' (Попробуем проверить на '+')
mov si,1 ; Да это '-' , Запомним знак числа
inc bp ; Перейдем к следующему символу;
dec cl ; Уменьшим счетчик обрабатываемых символов (уже 1 обработан)
jmp GO
PLUS:
cmp dl,2bh ; Это '+' ?
jne GO ; НЕТ это не плюс
inc bp ; Да это '+', Перейдем к следующему символу;
dec cl ; Уменьшим счетчик обрабатываемых символов
GO:
xor ax,ax ;
xor dx,dx ;
mov dl,[bp] ; В Dl Символы выбираемые из строки
inc bp ; К следующему байту строки
cmp dl,30h ; Проверим на dl < '0'
jl ERROR ; Это ASCII код меньше чем '0' (+,- уже проверены)
cmp dl,39h ; Проверим на dl > '9'
jg ERROR ; Да, не может быть символа больше 9 (ошибка)
sub dl,30h ; Это цифра от 0 до 9 => Dl
mov al,10 ; Сомножителю положено быть в Al
mul bl ; ( Изначально = 0 )
jo BAIT_OF ; Переполнение р.сетки байта
mov bl,al ; Сохраним промежуточное произведение
add ax,dx ; Сложим промеж произведение и очередной разряд
cmp ax,128
jg BAIT_OF
mov bl,al ; Сохраним промежуточный результат
loop GO ; Автоматически уменьшает CX на 1
; Определение знака числа
cmp si,0 ; Знак + ?
jne SET_MINUS ; число отрицательное (надо перевести в доп код)
test bl,80h ; Нет число <127
jnz BAIT_OF ; Для знакового числа это много >127
jmp DONE ; Все ОК + число в диапазоне <=127
;
SET_MINUS:
neg bl ; Переведем число в доп код
test bl,80h ; Число меньше -128
jz BAIT_OF ; Да оно меньше
jmp DONE ; Если нет переполнения то все ОК
;
; Обработка переполнения разрядной сетки
BAIT_OF:
call cr
lea dx, errmsg1
call write_str
call dos_exit

; Обработка ошибочных символов ()
ERROR:
call cr
lea dx, errmsg0
call write_str
call dos_exit
DONE:
xor dx,dx
mov dl,bl
pop si
pop bp
pop cx
pop bx
pop ax
ret
str_to_int endp

; Перевод строки и возврат каретки
cr proc near
push ax
push bx
push cx
mov bh,0
mov cx,1
mov al,0Dh ; Перевод строки
mov ah,0eh ; режим отображения TTY (Работают управляющие коды)
int 10h
mov al,0Ah ; Возврат каретки
mov ah,0eh ;
int 10h
pop cx
pop bx
pop ax
ret
cr endp
SergSpectr вне форума Ответить с цитированием
Старый 23.12.2010, 11:27   #4
SergSpectr
Новичок
Джуниор
 
Регистрация: 23.12.2010
Сообщений: 4
По умолчанию

; Очистка всего экрана, аналогично cls, Int 10h
clear_scr proc near
push ax
push bx
push cx
push dx
xor al,al ; al:=0 Очистить окно
xor cx,cx ; cx:=0 Верхний левый угол (0,0)
mov dh,24 ; Нижняя строка экрана 24
mov dl,79 ; Правый столбец экрана 79
mov bh,7 ; Нормальные атрибуты очистки
mov ah,6 ; вызов функции scroll_up
int 10h
pop dx
pop cx
pop bx
pop ax
ret
clear_scr endp


dot proc near
push ax
push bx
push cx
mov dl,2eh
mov ah,02h
int 21h
pop cx
pop bx
pop ax
ret
dot endp

; Выводит строку на экран int 21h
; Строка загружена DS:DX завершается символом $
write_str proc near
push ax
mov ah,09h
int 21h;
pop ax
ret
write_str endp


; Читает строку в буфер, формат входного буфера в Справке по 0Ah int 21h
; DS:DX
read_str proc near
push ax
mov al,var_a
mov ah,0Ah
int 21h;
pop ax
ret
read_str endp

dos_exit proc
mov ax,4c01h ; Выход в DOS c кодом 1
int 21h
dos_exit endp


code ends ;конец сегмента кода
end main ;конец программы с точкой входа main
SergSpectr вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Контроль ввода - римские цифры Kortes Visual C++ 23 24.01.2011 15:46
Паскаль,СЕМАНТИЧЕСКИЙ КОНТРОЛЬ ВВОДА ROMA2PVT Помощь студентам 9 28.03.2010 14:49
Контроль ввода данных в DBgrid(или Table?) Delphi Студло Помощь студентам 8 11.02.2010 18:37
Контроль ввода данных в классе oleg kutkov Общие вопросы C/C++ 1 14.04.2008 22:19