;Есть ли сумма подряд идущих положительных чисел превосходящих К. Пользователь сам задает размер массива, его содержимое и число К. 

;1 размер массива ввести с клавиатуры  
;2 массив ввести с клавиатуры
;3 напечатать введенный массив
;4 обработку массива оформить в виде процедуры
;5 массив и другие входные данные (если они есть) передать параметрами через стек

cseg segment                       
assume cs:cseg, ds:cseg, ss:cseg, es:cseg                   
org 100h                                              
Start:
  mov dx,offset Str_1                      ; Загружаем в dx адрес строки Str_1 (PA3MEP MACCuBA)
  call STRINGOUT                           ; Вызываем процедуру вывода строки на экран (STRINGOUT proc)
                                           ;  Введем размер массива (условие 1 задачи)             

  mov ah,1                                 ; Функция 1h прерывания 21h - Ввод символа с кл-ры.Ожидает нажатия клавиши и выводит соотв.символ  на экран. >        
                                           ; > При этом в al заносится код введенного символа.
 
  int 21h                                  ; Вводим 1-ю цифру (старш.разряд для 2-значного числа) либо единственную цифру (1-значн.число)
  int 21h                                  ; Если 1-значн. - жмем Enter. Если 2-значн.  - вводим 2-ю цифру (младш.разряд для 2-значн.числа)

   ;/////////////////////////////////////////////   
    push bp         ;сохранить указатель стека
    mov bp, sp        
    
    PUSH	AX		; сохраняем регистры 
    PUSH    CX      ;
	PUSH	BX		;
	PUSH	DX		;
    PUSH    DI      ;

ENTER_ARRAY:                               ; Метка начала ввода массива (условие 2) ,сохранения значения его элементов в стеке(условие 5) и  >
                                           ; > ..И паралелльной распечатки массива на экран (условие 3)
  
  mov dx,offset Str_2                      ; Загружаем адрес строки -  BBEDuTE MACCUB    
  call STRINGOUT                           ; Вызываем процедуру вывода строки на экран.
  xor cx,cx                                ; Очищаем cx, так как он нам понадобится для счета введенных элементов масс. Макс число  - 50 элементов.

INPUTA:                                    ; Метка ввода: Enter/символа МИНУС/первой (для 2-значн.числа) или единств. (для однозначн.) ПОЛОЖИТ.цифры.
                                           ; 

  mov ah,1                                 ; Для ввода и распечатки воспользуемся той же функцией 1h прерывания 21h
  int 21h                                  ; Введем либо первую/единственную цифру элемента массива (первую для 2-значн.числа,единственную - для 1-значн.),
                                           ; либо символ минус (это будет для нас индикатором отриц.элемента (числа), либо  -  Enter.
                                           ; Enter будет означать конец ввода и переход к процессу ввода числа К.
  
  cmp al,13                                ; Проверяем не нажат ли Enter..
  je PORTAL                                ; Если нажат, переходим к вводу числа К.
  cmp al,2dh                               ; Минус?  (2d  - код символа МИНУС)
  je NEGATIVE                              ; Если да,то переходим на метку ввода и преобразования ОТРИЦАТЕЛНОГО числа 
                                           ;
  sub al,30h                               ; Преобразование код-символа в цифру.Вычитаем 30 (для проверки, не введен ли символ из диапазона от 0 до 9
  cmp al,9                                 ; Сравниваем..
  jbe P                                    ; Если al<=9,значит символ из указанного диапазона.Прыгаем на метку Р
  sub al,27h                               ; Если условного перехода не происходит,значит введен символ из диапазона от А до F (отняв из al 27h, >
                                           ; > получим цифру из диапазона А-F,соответствующую введенному символу.
P:
  mov bh,al                                ; Преобразование закончено.Временно сохраним число в старшую половину bx на случай,если будет введена
                                           ; 2-я цифра текущего элемента т.е. младший разряд для 2-значн.числа.

INPUTB:                                    ; Метка ввода: Enter/запятой/ второй (для 2-значн.числа) цифры ПОЛОЖИТ.элемента.
                                           ; 
int 21h
  cmp al,13                                ; Нажат Enter?..
  je META                                  ; Если да,то переход на метку обработки и занесения в стек текущего 1-значн.ПОЛОЖИТ.эл-та массива.
  cmp al,2ch                               ; Запятая? 
  je ZAPYATAYA                             ; Если да,то переход на метку ZAPYATAYA
  mov bl,al                                ; Если нет,значит введена 2-я цифра 2-значн.положит.числа.Занесем ее в bl
                                           ; Теперь в bx 2-значн.число,допустим 15.Однако оба разряда занесены в разн.половинки регистра bx по отдельности 
                                           ; bh=01,bl=05;. Следовательно,bx=0105,а нам надо,чтобы был равен 0015.Преобразуем 0105 в 0015.. 
  shl bl,4                                 ; Свинем биты регистра bl на 4 позиции влево.bl=50 ;bx=0150. Число 15 теперь посередине bx...
  shr bx,4                                 ; Сдвинем биты BX! на 4 позиции вправо. Теперь bx=0015,что соответствует введенному нами значению.
  push bx                                  ; Сохраним в стек элемент массива (условие 5)
  inc cx                                   ; Увеличим счетчик кол-ва введенных элементов на один
  cmp cx,50                                ; Проверим на макс.число вводимых элементов..
  je ENTER_K                               ; Если да, то переходим к вводу числа К
  mov ah,2                                 ; Если нет,то автоматически запишем запятую,так как введено 2-значн.число (функц.2h прер.21h)
  mov dl,2ch                               ; в dl укажем код-символа,который хотим вывести на экран. 2c - код симола ','
  int 21h                                  ; Печать запятой 
  jmp INPUTA                               ; Переходим к вводу: Enter/'-'/ положит. цифры массива
ZAPYATAYA:                                 ; Переход на эту метку при условии нажатия запятой после 1-значн.положит.числа
  mov bl,bh                                ; Введено 1-зн.число,переместим bh в bl
  sub bh,bh                                ; bh обнулим (2-разряд нет). 
  push bx                                  ; bx=00xx (1-зн.число) Преобразование не нужно,поэтому помещаем текущий эл-нт в стек
  inc cx                                   ; Текущий элемент обработан,счетчик +1
  cmp cx,50                                ; 
  je ENTER_K                               ; Если введено 50 эл-тов, переходим к вводу числа К
  jmp INPUTA                               ; Если нет, переходим к вводу: Enter/'-'/ положит. цифры массива
PORTAL:
  jmp ENTER_K
NEGATIVE:                                  ; Метка ввода для отриц.числа.Аналог INPUTA с добавлением команды neg переводящей положит.число в отриц.
  mov ah,1                                 ;
  int 21h
  sub al,30h                               ;
  cmp al,9                                 ;
  jbe N                                    ;
  sub al,27h
N:
  mov dh,al
  int 21h
  cmp al,13
  je NEG_META
  cmp al,2ch
  je NEG_ZAPYATAYA
  mov dl,al
  shl dl,4
  shr dx,4
  neg dx                                   ; Команда neg переводит положительное число в отрицательное
  push dx
  inc cx
  cmp cx,50
  je ENTER_K
  xor dx,dx
  mov ah,2
  mov dl,2ch
  int 21h
  jmp INPUTA
META:
  mov bl,bh
  sub bh,bh
  push bx
  inc cx
  jmp ENTER_K
NEG_META:
  mov dl,dh
  sub dh,dh
  neg dx
  push dx
  inc cx
  jmp ENTER_K
NEG_ZAPYATAYA:
  mov dl,dh
  sub dh,dh
  neg dx
  push dx
  inc cx
  cmp cx,50
  je ENTER_K
  jmp INPUTA  


ENTER_K:                                  ; Метка ввода числа К
  mov dx,offset Str_3
  call STRINGOUT
  mov ah,1                                    
  int 21h                                 ; Вводим первое/единств.число К
  sub ah,ah                               ;Переводим код-символа в число>>>>
  sub al,30h                              ;>>>>>>
  cmp al,9                                ;>>>>>>
  jbe S                                   ;>>>>>>
  sub al,27h                              ;>>>>>>
S:                                        ;
  push ax                                 ;Заносим первую/единств.цифру в стек  
  mov ah,1
  int 21h                                 ; Вводим вторую цифру (для 2-значн.)/Enter                        
  sub ah,ah                               ; 
  cmp al,13                               ; Проверяем,не нажат ли Enter  
  je  VYZOV                               ; Если нажат,прыгаем на метку вызова процедуры  
  sub al,30h                              ; если нет,значит введена вторая цифра (для 2-значн.числа)
  cmp al,9                                ;
  jbe STK                                 ;                                            ;
  sub al,27h
STK: 
  mov bl,al                               ; младший разряд заносим в bl.
  pop ax                                  ; вынимаем в этом случае старший разряд из стека
  mov bh,al                               ; помещаем его в bh
  shl bl,4                                ; и делаем аналогичное преобразование:bx=0x0x > bx=0xx0 > bx= 00xx
  shr bx,4                                ; bx=
  mov ax,bx                               ; преобразованное число перенесем в ах
  push ax                                 ; и поместим в стек                


VYZOV:
  call CHECK_ARRAY                        ; Массив и число К введены и распечатаны.Вызываем процедуру просчета массива командой call


EXIT: 
  mov ah,10h
  int 16h                                 ; Выход из программы по нажатию любой клавиши..
  int 20h                                 ;


CHECK_ARRAY proc                          ; Процедура просчета массива

	
	
  xor bx,bx                               ; Обнулим регистры,которые будем изменять в процедуре.
  xor dx,dx                               ;
  pop si                                  ; Так как в стеке у нас массив и число К,а команда call поместила в стек адрес возврата из процедуры,то..
                                          ; ..вытащим из стека адрес возврата,поместив его в неиспользуемый программой регистр. Например в si
  pop ax                                  ; Вытаскиваем из стека число К                           
METKA:  
  pop dx                                  ; Вытаскиваем текущий элемент массива
  dec cx                                  ; Уменьшаем сх на 1. СХ равен кол-ву введенных элементов.
  test dx,dx                              ; Проверяем,не отрицат.ли число? 
  js NULLSUM                              ; Если да,то прыгаем на метку NULLSUM и обнуляем регистр bx,в котором будем суммировать пол.числа
  add bx,dx                               ; Если не конец массива/отр.число,значит у нас положит.Суммируем число в bx.Попросту - прибавим к bx.
  cmp bx,ax                               ; И сравниваем сумму (bx) со значением числа К (ах)
  ja STRCOMP                              ; Если bx БОЛЬШЕ,значит требуемая сумма найдена.Делаем джамп на STRCOMP и прекращаем проверку.
  cmp cx,0                                ; Проверяем,все ли эл-ты массива проверены
  jne METKA                               ; Если нет,переходим к следующему.
  jmp STRCOMP                             ; Если да, то прыгаем на STRCOMP
NULLSUM:                                  ; Переход на эту метку в случае,если число отрицательное 
  xor bx,bx                               ; Обнуляем сумму,содержащуюся в bx
  cmp cx,0                                ; 
  jne METKA
STRCOMP:                                  ; Метка повторного сравнения bx и ax для вывода соответсвующего сообщения
  cmp bx,ax                               ; Сравниваем для вывода соответств.строки YES/NO                                             
  jbe NO                                  ; Если bx<=ax, то прыгаем на метку NO 
YES:                                      ; Если же bx>ах,то выполняется эта метка (выводим строку 4(YES) и прыгаем на QUIT)
  mov dx,offset Str_4                     ; 
  call STRINGOUT
  jmp QUIT
NO:                                       ; Метка NO.Здесь выводим строку 5,в случае,если bx<=ax
  mov dx,offset Str_5
  call STRINGOUT
QUIT:
  push si                                 ; Помещаем заранее сохраненный в si адрес возврата из процедуры в стек 
  
  ;/////////////////////////
    POP DI      ;
	POP	DX		; восстанавливаем регистры
	POP	BX		;
	POP	CX		;
	POP	AX		;	
	POP BP      ;
	
  ret                                     ; Возврат из процедуры.
CHECK_ARRAY endp


STRINGOUT proc                            ; Процедура вывода строки
  mov ah,9
  int 21h
  ret
STRINGOUT endp


Str_1 db 'PA3MEP MACCuBA: $'
Str_2 db 10, 13, 'BBEDuTE MACCUB: $'
Str_3 db 10, 13, '4ucJIo K: $'
Str_4 db 10, 13, 'Required sum: YES$'     ;  bx>ax
Str_5 db 10, 13, 'Required sum: NO$'      ;  bx<=ax
     
cseg ends
end Start               