ПРИМЕР ВЫПОЛНЕНИЯ РАБОТЫ

Разработать подпрограмму, которая удаляет, начиная с задан­ной позиции строки, указанное число символов. Разработать про­грамму, которая вводит с клавиатуры строку, вводит позицию и длину удаляемой части строки и удаляет эту часть.

Текст программы:


locals __

model small

stack 100h

dataseg

MESS1 db 0dh,0ah,0dh,0ah,"Введите строку:",0dh,0ah,"$"

MESS2 db 0dh,0ah,"Введите позицию: $"

MESS3 db 0dh,0ah,"Введите число удаляемых символов: $"

MESS4 db 0dh,0ah,0dh,0ah,"Строка после удаления:",0dh,0ah,"$"

S_BUFLEN db 80 ; Макс. длина строки

S_FACTLEN db ? ; Длина фактически введенной строки

S_INPBUF db 80 dup (?) ; Введенная строка

N_BUFLEN db 3 ; Макс. длина числа при вводе

N_FACTLEN db ? ; Фактическая длина

N_INPBUF db 3 dup (?) ; Строка представления числа

POSDEL dw ? ; Позиция, начиная с которой удаляем

LENDEL dw ? ; Сколько символов удалить

 

codeseg

startupcode

; Ввод строки

MLOOP: lea DX, MESS1

mov AH, 09h

int 21h ;Приглашение к вводу строки

lea DX, S_BUFLEN

mov AH, 0Ah

int 21h ;Ввод строки

mov BL, S_FACTLEN

cmp BL, 0 ;Строка пустая?

jne LLL0 ;Нет - продолжать

jmp QUIT ;Закончить работу

LLL0: mov BH, 0 ;Дополнить длину до слова

add BX, 2 ; и получить адрес позиции

add BX, DX ; сразу после конца строки

mov byte ptr[BX],0;Записать признак конца строки

; Ввод позиции удаления

LLL1: lea DX, MESS2 ;Приглашение

mov AH, 09h ; к вводу

 

int 21h ; позиции удаления

lea DX, N_BUFLEN

mov AH, 0Ah

int 21h ;Ввод строки числа

lea BX, N_INPBUF ;Адрес строки представления числа

mov CL, N_FACTLEN ;Длина этой строки

call VAL ;Перевод в целое число

jc LLL1 ;Ошибка? - повторить ввод

cmp AL, 0 ;Ноль?

je LLL1 ;Повторить ввод

cmp AL, S_FACTLEN ;Превышает длину строки?

jg LLL1 ;Повторить ввод

mov POSDEL, AX ;Запомнить позицию удаления

; Ввод длины удаляемой части

LLL2: lea DX, MESS3 ;Приглашение

mov AH, 09h ; к вводу

int 21h ; числа удаляемых

lea DX, N_BUFLEN

mov AH, 0Ah

int 21h ;Ввод строки числа удаляемых

lea BX, N_INPBUF ;Адрес строки представления числа

mov CL, N_FACTLEN ;Длина этой строки

call VAL ;Перевод в целое число

jc LLL2 ;Ошибка? - повторить ввод

mov LENDEL, AX ;Запомнить число удаляемых

add AX, POSDEL ;Подсчитать, не выходит ли

dec AX ; удаляемая часть

cmp AL, S_FACTLEN ; за конец строки?

jg LLL2 ;Если да - повторить ввод

; Занесение параметров в стек и вызов п/п удаления

lea AX, S_INPBUF

push AX ;1-й параметр - адрес строки

push POSDEL ;2-й параметр - позиция удаления

push LENDEL ;3-й параметр - число удаляемых

call DELSUBS ;Вызов подпрограммы

; Вывод результата

lea DX, MESS4

mov AH, 09h

int 21h ;Заголовок вывода

lea BX, S_INPBUF

mov CX, 80

LLL3: cmp byte ptr [BX],0;Цикл поиска конца строки и выход

je LLL4 ; - когда конец строки найден

inc BX ;Сдвиг по строке

loop LLL3

LLL4: mov byte ptr [BX],'$';Заменить признак конца строки

lea DX, S_INPBUF

mov AH, 09h

int 21h ; Вывод результата

 

jmp MLOOP ; На повторение работы

 

QUIT: exitcode 0

 

;Действие:

; функция вычисляет целое число по его строковому представлению.

; Результат не может быть больше 255.

; Для неверно введенных чисел устанавливает флаг переноса

;Параметры:

; BX - адрес строки - предстваления числа

; CX - длина этой строки

;Возвращает:

; CF - установлен, если в строке не цифры, AX - не определен

; сброшен, строка нормальная, AX - число

; AX - преобразованное число, если сброшен

VAL proc near

push DX ;Сохранить все изменяемые регистры,

; кроме AX, в котором результат

mov CH, 0 ;Расширяем длину до слова

mov AX, 0 ;Начальное значение результата

mov DL, 10 ;Основание системы счисления

__1: imul DL ;Умножить на основание

jc __2 ;Переполнение байта?

mov DH, [BX] ;Очередная цифра

sub DH, '0' ;Получить значение цифры

jl __2 ;Это была не цифра!

cmp DH, 9

jg __2 ;Это опять же была не цифра!

add AL, DH ;+ значение цифры к результату

jc __2 ;Переполнение байта?

inc BX ;Сдвиг по строке

loop __1 ;Цикл по строке

jmp __3 ;Нормальное число

__2: stc ;Было переполн. - устанавливаем CF

__3: pop DX ;Восстановить все, что сохраняли

ret

VAL endp

 

; Подпрограмма удаления подстроки

DELSUBS proc near

arg __Ldel: word, __Pdel: word, __StrAdr: word = __ArgSize

;Params struc ;Структура стека после сохранения BP

; SaveBP dw ? ; Сохраненное значение BP

; SaveIP dw ? ; Адрес возврата

; LDel dw ? ; 3-й параметр - число удаляемых

; PDel dw ? ; 2-й параметр - позиция удаления

; StrAdr dw ? ; 1-й параметр - адрес строки

;Params ends

push BP ;Сохранить BP

mov BP, SP ;Теперь BP адресует стек ПОСЛЕ сохр.BP,

; но ДО сохранения остальных регистров

push ES AX SI DI CX ;Сохранить все изменяемые регистры

 

mov AX,DS ; ES будет указывать на

mov ES,AX ; сегмент данных

mov DI,__StrAdr ;Вычислить в DI адрес,

add DI,__PDel ; куда надо

dec DI ; пересылать символы

mov SI,DI ;А в SI - адрес,

add SI,__LDel ; откуда их пересылать

cld ;Продвигаться от начала строки к концу

__REPEAT:

movsb

cmp byte ptr [SI-1], 0

jne __REPEAT

pop CX DI SI AX ES ;Восстановить все, что сохраняли

pop BP

ret __ArgSize ;Убрать из стека 3 параметра-слова

DELSUBS endp

 

end

ВАРИАНТЫ ЗАДАНИЙ

В приведенных ниже вариантах заданий используется стан­дартное представление строк ASCII с кодом 0 в качестве ограни­чителя конца строки. Способ передачи параметров выбирается программистом произвольно. Рекомендуется зациклить программу по вводу, а признаком окончания работы считать ввод пустой строки.

1. Разработать подпрограмму, которая определяет, содержится ли одна заданная строка в другой заданной строке, и если да, то, начиная с какой позиции. Разработать программу, которая вводит с клавиатуры две строки и сообщает, содержится ли одна из них в другой и сколько раз.

2. Разработать подпрограмму, которая подсчитывает, сколько раз заданный символ встречается в строке. Разработать программу, которая вводит с клавиатуры строку, вводит число N и выдает список символов, которые встречаются в строке не менее чем N раз.

3. Разработать две подпрограммы, одна из которых соединяет две строки в одну, а другая обрезает строку до заданной длины (или дополняет пробелами, если длина строки меньше задан­ной). Разработать программу, которая вводит с клавиатуры число N, затем вводит несколько строк (конец ввода – пустая строка) и формирует новую строку, состоящую из первых N символов каждой введенной строки.

4. Разработать две подпрограммы, одна из которых сравнивает две строки по лексикографическому порядку, а другая обмени­вает значения двух строк. Разработать программу, которая вводит с клавиатуры несколько строк (конец ввода – пустая строка) и сортирует их в лексикографическом порядке.

5. Разработать подпрограмму, которая разбивает заданную строку на две части: первое слово строки (до первого пробела) и оста­ток строки (пробелы после первого слова отбрасываются). Раз­работать программу, которая вводит с клавиатуры строку и выводит каждое слово с новой строки.

6. Разработать подпрограмму, которая переставляет символы за­данной строки в обратном порядке. Разработать программу, ко­торая вводит с клавиатуры строку и переставляет в обратном порядке символы в каждом слове (слова разделяются пробе­лами).

7. Разработать подпрограмму, которая вставляет подстроку в строку, начиная с заданной позиции. Разработать программу, которая вводит с клавиатуры исходную строку, вводит под­строку и позицию вставки, вставляет подстроку в строку.

8. Разработать две подпрограммы, одна из которых преобразует любую заданную букву в заглавную (в том числе для русских букв), а другая - преобразует букву в строчную. Разработать программу, которая вводит с клавиатуры строку и заменяет первые буквы всех слов на заглавные, а остальные буквы - на строчные.

КОНТРОЛЬНЫЕ ВОПРОСЫ

1. Что такое «ближние» и «дальние» подпрограммы?

2. Как определяется, «ближний» или «дальний» вариант команды call использован в программе?

3. Какие еще способы передачи параметров можно предложить, кроме двух, описанных в данной работе?

4. Может ли массив быть параметром процедуры?

5. Нельзя ли адресовать параметры в стеке через регистр SP, не используя BP?

6. Что и как нужно изменить в программе из примера, если ис­пользуется версия ассемблера, не поддерживающая понятие структуры?

7. Изменить описание подпрограммы из примера с использова­нием упрощенных директив описания подпрограмм.

8. Что означает операнд команды ret?

9. Какой последовательностью команд можно было бы заменить команду ret 6?