Посвящается конкурентам. На Turbo Assembler фирмы Borland (теперь Inprise).

.MODEL tiny
.STACK 100h
.DATA
INCLUDE CYR_DEF.ASM

COUNTRYS db 'COUNTRYS.TXT',00h ; начало ШК - названия стран (3+3+24)
INVENTRY db 'INVENTRY.TXT',00h ; дата(4) - ШК(13) - полка(10) - к-во(2)
BC_NAMES db 'BC_NAMES.TXT',00h ; ШК (13) - название (16) - цена (9)
NAMES_BUF db 13 dup('0'),25 dup(' '),0Dh,0Ah,00h ; буфер BC_NAMES
INVEN_BUF db 29 dup(' '),0Dh,0Ah,00h ; буфер INVENTRY
COUNTR_BUF db 30 dup(' '),0Dh,0Ah,00h ; буфер COUNTRYS
UNKNOWN db 'НЕИЗВ.СТРАНА',0Dh,0Ah,00h
NOTFOUND db 'ШК НЕ НАЙДЕН...',00h
CRLF db 0Dh,0Ah,00h
PROMPT db '=>',00h
BARCODE db 13 dup('0'),00h
PRESSAKEY db 0Dh,0Ah,'НАЖМИТЕ ENT',00h
RECORDED_OK db 0Dh,0Ah,'ЗАПИСАНО...',00h
UPSIDEDOWN db 00h
F1_PRESSED db 0
MAINMENU db 'МЕНЮ (F1)'
db '-',14 dup('-'),'¬'
db '¦1 ИНВЕНТАР-ЦИЯ¦'
db '¦2 ВВОД ТОВАРА ¦'
db '¦3 СТРАНА РЕГ-И¦'
db '¦4 ВЫХОД ¦'
db 'L',14 dup('-'),'-','?',00h
HAND_1 dw 0 ; HANDLER файла COUNTRYS.TXT
HAND_2 dw 0 ; HANDLER файла INVENTRY.TXT
HAND_3 dw 0 ; HANDLER файла BC_NAMES.TXT
DATABUFFER db 0,0
FILENGTH dw 0
MESS1 db 'ФАЙЛ ПУСТ...',0
MESS2 db 'КОЛ-ВО:',0
MESS3 db 0Dh,0Ah,'ПОЛКА:',0
MESS4 db 'НАИМЕНОВАНИЕ:',0Dh,0Ah,0
MESS5 db 0Dh,0Ah,'ЦЕНА:',0
ERROR_WRITE db 'ОШИБКА ЗАПИСИ!',0

.CODE

mov ax,@data
mov ds,ax
mov es,ax
; --------------------------------------------------------------------------
mov ah,1Ah
mov bh,0 ;
mov al,1 ;
int 21h

call LOADFONT ; загрузить русские буквы
call SETUP_BC ; установить кодировки ШК

mov ah,3Dh ;
mov al,0 ; R/O
mov dx,OFFSET COUNTRYS
int 21h
jc NEXTFILE1 ; если невозможно открыть - черт с ним

mov HAND_1,ax
NEXTFILE1:
jmp OPEN_1
CREA_1:
mov ah,3Ch ;
mov dx,OFFSET INVENTRY
int 21h
jc NEXTFILE2 ; если невозможно создать - черт с ним
OPEN_1:
mov ah,3Dh ;
mov al,2 ; R/W
mov dx,OFFSET INVENTRY
int 21h
jc CREA_1 ; если невозможно открыть - создаем
mov HAND_2,ax


mov ah,42h ;
mov al,2 ;
mov bx,HAND_2 ;
mov cx,0 ; смещение 0 верхняя часть
mov dx,0 ; 0 нижняя часть
int 21h ;

mov ah,40h
mov bx,HAND_2
mov cx,31
mov dx,OFFSET INVEN_BUF
int 21h

mov ah,2Ch ;
int 21h

mov dl,10

mov ah,0
mov al,ch ; часы
idiv dl ; в al - десятки часов

add al,30h ; получаем символ
mov di,OFFSET INVEN_BUF
stosb ;

mov al,ah ; в al - единицы часов
add al,30h
mov di,OFFSET INVEN_BUF + 1
stosb

mov ah,0
mov al,cl ;
idiv dl ; в al - десятки минут

add al,30h ; получаем символ
mov di,OFFSET INVEN_BUF + 3
stosb ;

mov al,ah ; в al - единицы минут
add al,30h
mov di,OFFSET INVEN_BUF + 4
stosb

mov al,3Ah ; разделитель ':'
mov di,OFFSET INVEN_BUF + 2
stosb ;

mov ah,42h ; указатель -
mov al,2 ; на конец файла
mov bx,HAND_2 ;
mov cx,0 ; смещение 0 верхняя часть
mov dx,0 ; 0 нижняя часть
int 21h ;

mov ah,40h ; запись
mov bx,HAND_2
mov cx,31
mov dx,OFFSET INVEN_BUF
int 21h

NEXTFILE2:
jmp OPEN_2
CREA_2:
mov ah,5Bh ;
mov dx,OFFSET BC_NAMES
int 21h
jc SNOVAMENU ; если невозможно создать - черт с ним
OPEN_2:
; открыть файл
mov ah,3Dh ;
mov al,2 ; R/W
mov dx,OFFSET BC_NAMES
int 21h
jc CREA_2 ; если невозможно открыть - создаем

mov HAND_3,ax

SNOVAMENU:
mov ah,0
int 10h

call BELL

mov F1_PRESSED,0 ; сброс нажатия F1

; ----------------------------------
mov ah,9 ; напечатать
mov dx,OFFSET MAINMENU ; текст меню
int 21h

mov ah,1 ; ждать нажатия,
int 21h ; нажали - вывести на экран

cmp al,31h ; если нажали 1
je MENU_ONE
cmp al,32h ; если нажали 2
jne CONTINU
jmp MENU_TWO
CONTINU:
cmp al,33h ; если нажали 3
jne CONTINUE1
jmp MENU_THREE
CONTINUE1:
; если нажали 4 или другое
jmp KONEC


MENU_ONE: ; ИНВЕНТАРИЗАЦИЯ

mov ah,0 ; стереть
int 10h

call READ_BC ;

cmp F1_PRESSED,1
jne CONTIN
jmp SNOVAMENU
CONTIN:
call CLEAR_NAMES_BUF
call CLEAR_INVEN_BUF

mov ah,42h ;
mov al,2 ;
mov bx,HAND_3 ; BC_NAMES
mov cx,0 ; смещение 0 верхняя часть
mov dx,0 ; 0 нижняя часть
int 21h ; для определения длины файла в DX:AX

mov FILENGTH,ax ; записали в память (DX не нужен,
; если длина файла < 64K)
cmp ax,40
ja GOOD_1 ; если в файле не набралось байт на 1 запись
mov ah,9 ; напечатать сообщение
mov dx,OFFSET MESS1
int 21h
jmp MO_22
GOOD_1:
mov ah,42h ;
mov al,0 ;
mov bx,HAND_3 ; BC_NAMES
mov cx,0 ; смещение 0 верхняя часть
mov dx,0 ; 0 нижняя часть
int 21h ;

jnc MO_S1 ; если не получилось - СКАЗАТЬ, что такого ШК нет
jmp MO_21
MO_S1:
mov ah,3Fh ; прочитать
mov bx,HAND_3 ; из файла
mov cx,40 ; 40 байт
mov dx,OFFSET NAMES_BUF ; в буфер
int 21h ;

jnc MO_S7 ; если не получилось - СКАЗАТЬ, что такого ШК нет
jmp MO_21
MO_S7:
cmp ax,38 ; сравнить требуемое кол-во байт со считанным (ax)
jnb MO_S8 ; если прочитано менее 38 - конец файла
jmp MO_21
MO_S8:

mov cx,0
TAKENEXT:
mov ax,OFFSET BARCODE ; i-й символ ШК
add ax,cx
mov si,ax
mov ax,OFFSET NAMES_BUF ; c i-м символом записи
add ax,cx
mov di,ax
cmpsb
jne MO_S1 ; если <> то сразу читать следующую запись
; если пока равно, посмотреть: cx < 13 ?
inc cx
cmp cx,12
jbe TAKENEXT ; на следующий байт
; если сравнены уже все байты - найдено!

mov ah,9 ; напечатать
mov dx,OFFSET NAMES_BUF + 13
int 21h

mov ah,9 ; напечатать
mov dx,OFFSET MESS2 ; введите кол-во
int 21h
WAIT_KBD:
mov ah,0Bh ; проверить буфер клавы
int 21h
cmp al,0 ; если ничего - ждать
je WAIT_KBD
; иначе - брать из клавы

mov cx,0 ; обнулить счетчик
READ_KBD:
mov ah,1 ; прочитать из клавы и вывести на экран
int 21h

cmp al,0Dh ; нажата CRLF ?
je FINISHED

cmp al,86h ; это F1 ?
jne NEXT_CHAR
jmp SNOVAMENU
NEXT_CHAR:
; проверить, это цифры? - от 30h до 39h
; если да - загнать в DATABUFFER и-тый

cmp al,30h
jb READ_KBD ; если меньше 30 - не цифра - игнорируем
cmp al,39h
ja READ_KBD ; если больше 39 - не цифра - игнорируем
mov di,OFFSET DATABUFFER ; в di - адрес DATABUFFER[cx]
add di,cx
stosb ; нажата цифра - запишем
inc cx
cmp cx,3
jae OKAY ; уже хватит
jmp READ_KBD
FINISHED:
mov di,OFFSET DATABUFFER ; в di - адрес DATABUFFER[cx]
add di,cx
mov al,0
stosb ; запишем 00h
OKAY:

mov ah,9 ; напечатать
mov dx,OFFSET MESS3 ; введите полку
int 21h
WAIT_KBD1:
mov ah,0Bh ; проверить буфер клавы
int 21h
cmp al,0 ; если ничего - ждать
je WAIT_KBD1
; иначе - брать из клавы

mov cx,17 ; обнулить счетчик (начало поля ПОЛКА в буфере)
READ_KBD1:
mov ah,1 ; прочитать из клавы и вывести на экран
int 21h

cmp al,0Dh ; нажата CRLF ?
je OKAY1

cmp al,86h ; это F1 ?
jne NEXT_CHAR1
jmp SNOVAMENU
NEXT_CHAR1:
mov di,OFFSET INVEN_BUF ; в di - адрес INVEN_BUF[cx]
add di,cx
stosb ; нажата клавиша - запишем
inc cx
cmp cx,27
jae OKAY1 ; уже хватит
jmp READ_KBD1
OKAY1:

mov ah,2Ah ; узнать дату
int 21h

mov ah,30h ; символ десятков

cmp dh,10
jb DATE_1
mov ah,31h ; если есть десятки в номере месяца (10-12)
sub dh,10

DATE_1: ; если десятков в номере месяца нет (1-9)

mov al,ah
mov di,OFFSET INVEN_BUF
stosb ;

mov al,dh
add al,30h

mov di,OFFSET INVEN_BUF + 1
stosb ;

mov ah,30h ; символ десятков

cmp dl,10
jb DATE_2 ; если десятков в дне месяца нет (1-9)
; если есть десятки в дне месяца (10-31)
cmp dl,20
jb DATE_3
cmp dl,30
jb DATE_4
mov ah,33h ; (30-31)
sub dl,30
jmp DATE_2
DATE_4:
mov ah,32h ; (20-29)
sub dl,20
DATE_3:
mov ah,31h ; (10-19)
sub dl,10
DATE_2:
mov al,ah
mov di,OFFSET INVEN_BUF + 2
stosb ;

mov al,dl
add al,30h

mov di,OFFSET INVEN_BUF + 3
stosb ;

cld
mov cx,13 ; копируем BARCODE в INVEN_BUF[4:16]
mov di,OFFSET INVEN_BUF + 4
mov si,OFFSET BARCODE
rep movsb

mov cx,2 ; копируем кол-во в INVEN_BUF[27:28]
mov di,OFFSET INVEN_BUF + 27
mov si,OFFSET DATABUFFER
rep movsb

mov ah,42h ; указатель -
mov al,2 ; на конец файла
mov bx,HAND_2 ;
mov cx,0 ; смещение 0 верхняя часть
mov dx,0 ; 0 нижняя часть
int 21h ;

mov ah,40h ; запись
mov bx,HAND_2
mov cx,31
mov dx,OFFSET INVEN_BUF
int 21h
jc ERR_WRITE
cmp ax,31 ; сколько байт записано? 31?
je MO_22 ; если да - идем дальше
ERR_WRITE:
mov ah,9 ; напечатать
mov dx,OFFSET ERROR_WRITE
int 21h

jmp MO_22
MO_21:
mov ah,9 ; напечатать
mov dx,OFFSET NOTFOUND
int 21h
MO_22:
mov ah,9 ; напечатать
mov dx,OFFSET PRESSAKEY ; "нажмите"
int 21h

mov ah,7 ; ждем нажатия
int 21h

jmp MENU_ONE


MENU_TWO: ; ВВОД ТОВАРА
mov ah,0 ; стереть экран
int 10h

call READ_BC ; прочитать ШК в DS:[BARCODE]

cmp F1_PRESSED,1
jne MTWO_1
jmp SNOVAMENU
MTWO_1:
call CLEAR_NAMES_BUF ; очистить буфер NAMES_BUF

mov ah,9 ; напечатать
mov dx,OFFSET MESS4 ; введите наименование
int 21h
WAIT_KBD3:
mov ah,0Bh ; проверить буфер клавы
int 21h
cmp al,0 ; если ничего - ждать
je WAIT_KBD3
; иначе - брать из клавы

mov cx,13 ; обнулить счетчик (начало поля ИМЯ в буфере)
READ_KBD3:
mov ah,1 ; прочитать из клавы и вывести на экран
int 21h

cmp al,0Dh ; нажата CRLF ?
je OKAY3

cmp al,86h ; это F1 ?
jne NEXT_CHAR3
jmp SNOVAMENU
NEXT_CHAR3:
cmp al,8h
je PROCEED4 ; если BackSpace

mov di,OFFSET NAMES_BUF ; в di - адрес NAMES_BUF[cx]
add di,cx
stosb ; нажата клавиша - запишем
inc cx
cmp cx,29
jae OKAY3 ; уже хватит
jmp READ_KBD3
PROCEED4:
cmp cx,13
je READ_KBD3
dec cx
jmp READ_KBD3
OKAY3:
; ввести цену

mov ah,9 ; напечатать
mov dx,OFFSET MESS5 ; введите цену
int 21h
WAIT_KBD5:
mov ah,0Bh ; проверить буфер клавы
int 21h
cmp al,0 ; если ничего - ждать
je WAIT_KBD5
; иначе - брать из клавы

mov cx,29 ; обнулить счетчик
READ_KBD5:
mov ah,1 ; прочитать из клавы и вывести на экран
int 21h

cmp al,0Dh ; нажата CRLF ?
je OKAY5

cmp al,86h ; это F1 ?
jne NEXT_CHAR5
jmp SNOVAMENU
NEXT_CHAR5:
; проверить, это цифры? - от 30h до 39h
; если да - загнать и-тый
cmp al,8h
je PROCEED6 ; если BackSpace
cmp al,2Eh
je PROCEED5 ; если точка
cmp al,30h
jb READ_KBD5 ; если меньше 30 - не цифра - игнорируем
cmp al,39h
ja READ_KBD5 ; если больше 39 - не цифра - игнорируем
PROCEED5:
mov di,OFFSET NAMES_BUF ; в di - адрес NAMES_BUF[cx]
add di,cx
stosb ; нажата клавиша - запишем
inc cx
cmp cx,38
jae OKAY5 ; уже хватит
jmp READ_KBD5
PROCEED6:
cmp cx,29
je READ_KBD5
dec cx
jmp READ_KBD5
OKAY5:
cld
mov cx,13 ; копируем BARCODE в NAMES_BUF[0:12]
mov di,OFFSET NAMES_BUF
mov si,OFFSET BARCODE
rep movsb

mov ah,42h ; указатель -
mov al,2 ; на конец файла
mov bx,HAND_3 ; BC_NAMES
mov cx,0 ; смещение 0 верхняя часть
mov dx,0 ; 0 нижняя часть
int 21h ;

mov ah,40h ; запись
mov bx,HAND_3
mov cx,40
mov dx,OFFSET NAMES_BUF
int 21h
jc ERR_WRITE5
cmp ax,40 ; сколько байт записано? 40?
je MO_225 ; если да - идем дальше
ERR_WRITE5:
mov ah,9 ; напечатать
mov dx,OFFSET ERROR_WRITE
int 21h
MO_225:
mov ah,9 ; напечатать
mov dx,OFFSET RECORDED_OK ; "нажмите"
int 21h

mov ah,7 ; ждем нажатия
int 21h

jmp MENU_TWO

MENU_THREE: ; ПРОВЕРКА СТРАНЫ
mov ah,0 ; стереть экран
int 10h

call READ_BC ; прочитать ШК в DS:[BARCODE]

cmp F1_PRESSED,1
jne MO_SEARCH0
jmp SNOVAMENU

MO_SEARCH0:
mov ah,42h ; указатель -
mov al,0 ; на начало файла
mov bx,HAND_1 ; COUNTRYS
mov cx,0 ; смещение 0 верхняя часть
mov dx,0 ; 0 нижняя часть
int 21h ; вызвать эту функцию

jc MO_1 ; если не получилось - просто продолжить работу

MO_SEARCH1:
mov ah,3Fh ; прочитать
mov bx,HAND_1 ; из файла
mov cx,30 ; 30 байт
mov dx,OFFSET COUNTR_BUF ; в буфер
int 21h ; вызвать эту функцию

mov ah,42h ; указатель -
mov al,1 ; с текущей позиции

mov bx,HAND_1 ; переместить на
mov cx,0 ; смещение верхняя часть
mov dx,2 ; нижняя часть (+2 байта CR/LF)
int 21h ; вызвать эту функцию
jc MO_1 ; если не получилось - просто продолжить работу

mov si,OFFSET BARCODE ; первый символ ШК
mov di,OFFSET COUNTR_BUF + 3 ; c 4-м символом записи
cmpsb
ja MO_SEARCH1 ; если a > x2 - на следующую запись

mov si,OFFSET BARCODE + 1 ; 2-й символ ШК
mov di,OFFSET COUNTR_BUF + 4 ; c 5-м символом записи
cmpsb
ja MO_SEARCH1 ; если b > y2 - на следующую запись

mov si,OFFSET BARCODE + 2 ; 3-й символ ШК
mov di,OFFSET COUNTR_BUF + 5 ; c 6-м символом записи
cmpsb
ja MO_SEARCH1 ; если c > z2 - на следующую запись

mov di,OFFSET BARCODE ; первый символ ШК
mov si,OFFSET COUNTR_BUF ; c 1-м символом записи
cmpsb
ja MO_1 ; если a < x1 - сразу выход

mov di,OFFSET BARCODE + 1 ; 2-й символ ШК
mov si,OFFSET COUNTR_BUF + 1 ; c 2-м символом записи
cmpsb
ja MO_1 ; если b < y1 - сразу выход

mov di,OFFSET BARCODE + 2 ; 3-й символ ШК
mov si,OFFSET COUNTR_BUF + 2 ; c 3-м символом записи
cmpsb
ja MO_1 ; если c < z1 - сразу выход

; здесь получили нужную запись, печатаем страну!
mov ah,9 ; напечатать
mov dx,OFFSET COUNTR_BUF+6 ;
int 21h

jmp MO_2
MO_1:
; страна неизвестна
mov ah,9 ; напечатать
mov dx,OFFSET UNKNOWN
int 21h
MO_2:
mov ah,9 ; напечатать
mov dx,OFFSET PRESSAKEY ; "нажмите"
int 21h

mov ah,7 ; ждем нажатия
int 21h

jmp MENU_THREE

KONEC:
mov ah,3Eh ;
mov dx,OFFSET INVENTRY
int 21h

mov ah,3Eh ;
mov dx,OFFSET COUNTRYS
int 21h

mov ah,3Eh ;
mov dx,OFFSET BC_NAMES
int 21h

mov ah,0
int 21h

;------------------------------------------------------------------------
LOADFONT proc near

mov ah,1 ; маленький шрифт
int 9

mov ah,6 ; загрузить новый
mov al,1 ; мелкий шрифт
mov cl,128
mov dx,OFFSET AAO
INCYCLE:
int 9

inc cl ; следующий код символа (до 159 включительно)
add dx,6 ; байт данных

cmp cl,160
jb INCYCLE

mov cl,196 ;
mov dx,OFFSET MNS
int 9

mov cl,192 ;
mov dx,OFFSET LNU
int 9

mov cl,218 ;
mov dx,OFFSET LVU
int 9

ret

LOADFONT endp
; --------------------------------------
SETUP_BC proc near ; УСТАНОВКА КОДИРОВОК ШК

mov ah,1Fh ; работа с
mov bh,1 ; кодировками ШК
mov al,0 ; ВЫключить
mov bl,0 ; ВСЕ кодировки
int 21h

mov ah,1Fh ; работа с
mov bh,1 ; кодировками ШК
mov al,1 ; Включить
mov bl,4 ; EAN
int 21h

mov ah,1Fh ; работа с
mov bh,3 ; кодировками
mov al,00001101b ; Включить, контрольная, передняя
mov bl,13h ; EAN-13
int 21h

mov ah,1Fh ; работа с
mov bh,3 ; кодировками
mov al,00000101b ; Включить, контрольная цифра
mov bl,14h ; EAN-8
int 21h

ret

SETUP_BC endp

; --------------------------------------

READ_BC proc near ; ЧТЕНИЕ ШК из порта или клавы

mov al,32 ; очистка
mov cx,13
mov di,OFFSET BARCODE ;
rep stosb

NEXTSCAN: mov ah,51h ; порт сканера
mov al,1 ; включить
int 21h

mov ah,9 ; напечатать
mov dx,OFFSET PROMPT ; приглашение
int 21h
WAITDATA:
mov ah,0Bh ; проверить буфер клавы
int 21h
cmp al,0 ; если ничего - ждать из порта сканера
je CHECKPORT

; иначе - брать из клавы
mov cx,0 ; обнулить счетчик
FROMKEYB:
mov ah,1 ; проверить, это цифры? - от 30h до 39h
int 21h
; если да - загнать в BARCODE и-тый, пока не нажато CRLF
cmp al,0Dh
je CR_PRESSED ; нажата CRLF

cmp al,86h
jne NEXT_CH ; это F1 ?
mov F1_PRESSED,1 ; признак нажатия F1
jmp GONEXT
NEXT_CH:
cmp al,30h
jb CHECKPORT
cmp al,39h
ja CHECKPORT
mov di,OFFSET BARCODE ; в di - адрес BARCODE[cx]
add di,cx
stosb
inc cx
cmp cx,13
jae GONEXT ; уже хватит
jmp FROMKEYB
CR_PRESSED:
mov di,OFFSET BARCODE
add di,cx
mov al,0
stosb ;
jmp GONEXT ;
CHECKPORT:
mov ah,50h ;
mov dx,OFFSET BARCODE ;
int 21h

cmp ax,1 ;
je WAITDATA ;
SHOW_BC:
mov ah,9 ; напечатать
mov dx,OFFSET BARCODE ; строку
int 21h

cmp cl,0 ; флаг равен 0 (перевернут)?
jne GONEXT ; нет - дальше

mov ah,9 ; напечатать
mov dx,OFFSET UPSIDEDOWN ; строку
int 21h

GONEXT:
mov ah,9 ; напечатать
mov dx,OFFSET CRLF ; строку
int 21h

mov ah,9 ; напечатать
mov dx,OFFSET CRLF ; строку
int 21h

mov ah,51h ; порт сканера
mov al,0 ; выключить
int 21h

ret

READ_BC endp
; --------------------------------------
BELL proc near ; ЗВУКОВОЙ СИГНАЛ

mov ax,3 ; beeper частота
mov bx,1 ; длительность
int 31h

mov ax,4 ; beeper
mov bx,1
int 31h

mov ax,6 ; beeper
mov bx,0
int 31h

ret
BELL endp
;--------------------------------------------------
CLEAR_NAMES_BUF proc near
mov al,32
mov cx,38
mov di,OFFSET NAMES_BUF ; в di - адрес NAMES_BUF
rep stosb
ret
CLEAR_NAMES_BUF endp
;--------------------------------------------------
CLEAR_INVEN_BUF proc near
mov al,32
mov cx,29
mov di,OFFSET INVEN_BUF ; в di - адрес INVEN_BUF
rep stosb
ret
CLEAR_INVEN_BUF endp
;--------------------------------------------------
end ; конец всей программы

В начало