Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ;Задание 6, вариант 12.
- ;Выдать все строки с номерами 21 и 55
- ;Выдать все строки с символом "
- .MODEL TINY ;Будем использовать формат исполняемого файла COM
- .CODE ;Сегмент кода (он же в нашем случае и сегмент данных и стека одновременно)
- ORG 100h ;Программный счетчик ставим на 100h, это требуется для COM файлов.
- Begin:
- ;По началу из-за особенностей COM файлов у нас CS = SS = DS = ES.
- ;То есть мы будем использовать один сегмент для всего. Стек при этом растет с конца
- JMP Main ;Переходим на стартовую метку программы
- ReqNum1 EQU 21 ;Требуемые номера
- ReqNum2 EQU 55
- ReqChar = """" ;требуемый символ. Повторен 2 раза из-за экранирования.
- ;Т.к помещаем двойные кавычки в двойные кавычки.
- ;Далее текстовый строки. Для удобства форматирования вывода могут содержать
- ;в себе символы новой строки и перевода каретки.
- NotFoundNum1 DB "Строка с номером 21 не найдена", 13, 10, "$"
- NotFoundNum2 DB "Строка с номером 55 не найдена", 13, 10, "$"
- NotFoundChar DB "Строка, содержащая символ "" не найдена", 13, 10, "$"
- StringN DB "Строка с символом "": $"
- StringNum1 DB "Строка #21: $"
- StringNum2 DB "Строка #55: $"
- CRLF DB 13, 10, "$"
- StrI DB 1 ;Текущий номер строки
- LastFlag DB 0 ;Была ли найденная строка последней?
- StartPosition DW 0 ;Позиция и длина последней найденной строки
- StartLength DW 0
- Num1Out DB 0 ;Флаги. Хранят статус факта вывода строк
- Num2Out DB 0
- CharOut DB 0
- LaunchString DB "Строка запуска программы # : $"
- ;Начало сегмента кода
- Main: ;Главная функция. С нее начинается работа программы
- MOV AX,[ES:2Ch] ;AX - сегмент переменных среды
- MOV ES,AX ;ES теперь - сегмент переменных среды
- CheckLoop:
- CALL GetString ;Получаем строку
- CALL CheckStrForSymbols ;Проверяем ее на наличие требуемых символов
- CALL CheckNumber ;Проверяем строку по номерам (нужно ли выводить)
- INC BYTE PTR [StrI] ;Переходим к следующей строке
- CMP BYTE PTR [LastFlag],1 ;Если строки еще остались - прочитаем еще
- JNE CheckLoop
- CMP BYTE PTR [Num1Out],1 ;Если первая строка не была выведена
- JE CheckNext
- MOV DX,OFFSET NotFoundNum1 ;То доложим об этом, как требует условие
- CALL Print
- CheckNext:
- CMP BYTE PTR [Num2Out],1 ;Тоже самое и для второй строки
- JE SkipIt
- MOV DX,OFFSET NotFoundNum2
- CALL Print
- SkipIt:
- CMP BYTE PTR [CharOut],0 ;И тоже самое для строки с символом
- JNZ Done
- MOV DX,OFFSET NotFoundChar ;Выведем сообщение, если не находили таких строк
- CALL Print
- Done:
- ;Теперь остается вывести строку запуска программы и ее номер.
- ;Сейчас DI практически на нее указывает, не считая 3 байт.
- MOV SI,OFFSET LaunchString + 28 ;SI будет указывать
- ;Чтобы получить строку номера - придется делить:
- MOV AL,[StrI] ;AL - номер строки
- MOV BL,10 ;Делить будет на 10
- DivLoop:
- XOR AH,AH ;Обнулим остаток
- DIV BL ;Делим. В AH попадет остаток от деления
- MOV BYTE PTR [SI],AH ;Записываем его в строку
- ADD BYTE PTR [SI],"0" ;И превращаем в символ числа
- DEC SI ;К предыдущему символу
- TEST AL,AL ;Продолжаем, пока результат не 0
- JNZ DivLoop
- MOV DX,OFFSET LaunchString ;Выведем комментарий к строке вместе с номером
- CALL Print
- ADD DI,3 ;Заставим DI указывать на строку запуска
- CALL GetString ;И отобразим ее тоже.
- CALL Output
- MOV AX,4C00h ;Завершаем программу и выходим в DOS
- INT 21h
- ;Проверяет, какой номер у полученной строки. Если его нужно вывести - выводит
- CheckNumber:
- MOV AL,ReqNum1 ;AL - первый из номеров итнересующих нас строк
- CMP BYTE PTR [StrI],AL ;Индекс текущей строки совпадает с ним?
- JNE CheckSecond ;нет - переходим к следующей
- MOV DX,OFFSET StringNum1 ;Иначе выводим сообщение, что строка найдена
- CALL Print
- MOV DI,[StartPosition] ;И саму строку
- MOV CX,[StartLength]
- CALL Output
- MOV DX,OFFSET CRLF
- CALL Print
- MOV BYTE PTR [Num1Out],1
- INC DI
- ;Вывести первую строку
- CheckSecond:
- MOV AL,ReqNum2 ;Аналогично и для второй строки
- CMP BYTE PTR [StrI],AL
- JNE NotThisTime
- MOV DX,OFFSET StringNum2
- CALL Print
- MOV DI,[StartPosition]
- MOV CX,[StartLength]
- CALL Output
- MOV DX,OFFSET CRLF
- CALL Print
- MOV BYTE PTR [Num2Out],1
- INC DI
- NotThisTime:
- RET
- ;Проверяет, имеются ли в полученной строке искомый нами символ.
- ;Если да - выводит такую строку
- ;Предполагает, что на входе CX - длина строки, DI - ее начало
- CheckStrForSymbols:
- MOV [StartPosition],DI ;Сохраняем в переменные начало строки и ее длину
- MOV [StartLength],CX
- MOV AH,ReqChar ;Ah - код интеерсующего нас символа
- NewChar:
- CMP [ES:DI],AH ;Является ли текущий символ строки искомым?
- JE Found ;Если да, перейдем к выводу строки
- INC DI ;Иначе проверим следующий символ
- DEC CX
- JNZ NewChar ;Пока строка не кончилась
- JMP NotFound
- Found:
- MOV BYTE PTR [CharOut],1 ;Ставим флаг, что нашли хоть одну строку с указанным символом
- MOV DX,OFFSET StringN ;И выводим эту строку с комментарием
- CALL Print
- MOV DI,[StartPosition]
- MOV CX,[StartLength]
- CALL Output
- MOV DX,OFFSET CRLF
- CALL Print
- INC DI
- RET
- NotFound:
- INC DI
- RET
- ;Получает очередную строку из сегмента переменных среды.
- ;Предполагает, что ES:DI - сегмент переменных среды
- ;Устанавливает LastFlag в 1, если полученная строка была последней. Иначе 0.
- ;На выходе DI - начало строки. CX - ее длина.
- GetString:
- PUSH DI
- MOV CX,65535 ;Ведем поиск по всему сегменту
- XOR AL,AL ;Ищем нули
- CLD ;Направление поиска на инкремент
- REPNE SCASB ;Ищем
- CMP BYTE PTR [ES:DI],0 ;Если сразу же после нуля есть еще один
- JE LastString ;то это была последняя строка
- POP DI ;Восстановим старое значение указателя на строку
- NEG CX ;И приведем в порядок CX, чтобы показывал длину найденной строки
- SUB CX,2
- RET
- LastString:
- POP DI ;Аналогично и тут
- NEG CX
- SUB CX,2
- MOV BYTE PTR [LastFlag],1
- RET
- ;Выводит строку символов с помощью функции AH-02h прерывания INT 21h
- ;Начало строки - ES:DI. Символы выводятся в количестве CX штук
- Output:
- MOV AH,02h ;INT 21h, 02h - вывод символа
- StartLoop:
- MOV DL,[ES:DI] ;DL - код текущего символа строки
- INT 21h ;Выводим
- INC DI ;и переходим к следующему символу
- LOOP StartLoop ;Так, пока не отобразим все CX символов
- ExitLoop:
- RET
- Print: ;Просто функция вывода строки, чтобы
- MOV AH,09H ;писать не 3 строчки на вывод, а две.
- INT 21h
- RET
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement