Текст задания:
Составить внешнюю подпрограмму для варианта задания, соответствующего порядковому номеру студента в списке группы. Подпрограмму оформить в отдельном модуле. Для проведения отладки подпрограммы необходимо так же составить основную программу на языке ассемблера, вызывающую составленную подпрограмму как внешнюю. Тип вызова выбирается самостоятельно.
15. function DeTab8(S: string): string.
Возвращает строку, в которой все вхождения кода горизонтальной табуляции Ht=9 расширены пробелами. Для этого строка просматривается слева направо и встречающиеся коды Ht заменяются на требуемое в данной позиции количество пробелов. Количество пробелов можно определить из формулы, связывающей индекс произвольной текущей позиции i c индексом следующей позиции табуляции j:
— j=(((i-1)/8)+1)*8+1,
где i,j — целые и отсчитываются от единицы.
ГСА процедуры:
Текст программы:
Файл «lab3.asm» (подпрограмма):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
code segment byte public assume cs:code,ds:code public Change ;--------------------------------------------------------------- ; function Change(S: string; Ch1, Ch2: char): string, ; возвращает строку, в которой все вхождения Сh1 заменены на Ch2 ;--------------------------------------------------------------- Change proc far ; адреса параметров в стеке: S equ dword ptr [bp+6] ; параметр S Res equ dword ptr [bp+10] ; параметр Res (результат) push bp ; сохранение bp mov bp,sp ; настройка bp на вершину стека push ds ; сохранение ds les di,Res ; es:di:=адрес результата lds si,S ; ds:si:=адрес исходной строки cld ; очистка флага направления (инкремент) lodsb ; al:=(ds:[si]), si:=si+1 (al - длина S) ; mov al,0ffh; stosb ; (es:[di]):=al, di:=di+1 (запись длины) mov ch,0 ; подготовка сх в качестве счетчика mov cl,al ; количества символов строки S jcxz Exit ; выход, если S - пустая строка (сх=0) ;push bx; ;C dw 00h; mov bx,00h; ;mov C,bx; ;pop bx; Repeat: push cx; ;pop bx; lodsb ; считать в al очередной символ S ;push bx; ;push cx; ;mov bx,C; ;inc bx; cmp al,09h ; символ равен Tab? mov cx,01h; jne Save ; нет, сохранить без изменений mov cx,bx; sub cx,1; shr cx,3; ;shr cx,1; ;shr cx,1; add cx,1; shl cx,3; ;shl cx,1; ;shl cx,1; sub cx,bx; jnz Replace; mov cx,08h; Replace: mov al,20h ; да, заменить на Ch2 ;mov C,bx; Save: ;pop bx; inc bx; stosb ; записать очередной символ результата Res ;push bx; loop Replace; pop cx; loop Repeat ; повторять, пока есть символы в S (cx>0) Exit: les di,Res; ; mov bx, 0ffh; mov ax,bx; stosb; pop ds ; восстановить ds pop bp ; восстановить bp (sp изменен корректно) ret 4 ; выход с удалением параметров Ch1, Ch2 и ; адреса S (Res удалять нельзя!) Change endp code ends end |
Файл «lab3main.asm» (вызов подпрограммы):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
code segment assume cs:code,ds:code org 100h extrn Change:far ; описание внешней far-процедуры Example:mov ax,cs ; настройка сегмента данных mov ds,ax ; на сегмент кода ; подготовка параметров вызова Change(S,'1','2') push ds ; сегмент строки результата Res mov ax,offset Res push ax ; смещение Res push ds ; сегмент исходной строки S mov ax,offset S push ax ; смещение S ;mov al,'1' ; параметр Ch1 = '1' ;push ax ; ;mov al,'2' ; параметр Ch2 = '2' ;push ax ; call Change ; far-вызов Change ; чтение адреса результата функции Change из стека pop bx ; bx:=смещение Res pop ds ; ds:=сегмент Res mov ch,0 ; подготовка в сх длины строки Res mov cl,[bx] jcxz Exit ; выход, если строка Res пуста Write: inc bx ; продвижение указателя символа mov dl,[bx] ; dl:=очередной символ Res mov ah,2 ; вывод символа из dl на экран int 21h ; средствами DOS loop Write ; цикл по длине строки Res Exit: mov ax,4c00h ; завершение программы int 21h ; чеpез функцию DOS S db 7, ' 123 34', 248 dup(?) Res dw 128 dup(?) code ends end Example |
Файл «lab3asm.PAS»:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
{$L lab3.obj} {$F+} function Change(S:string):string;external; var S:string; begin Writeln('Microsoft DOS Protected Mode Copyright 2006'); Readln(S); {S:='111'+Chr(9)+'111'+Chr(9)+'1111';} { S:='11111111'+Chr(9)+'1';} S:=Chr(9)+'1'; Writeln(S,'L=',Length(S)); S:=Change(S); Writeln(S,'L=',Length(s)); Readln(S); end. |
Результат работы программы:
№ Опыта | Вход | Выход |
1 | 111<Tab>111<Tab>1111 | 111<5 Пробелов>111<5 Пробелов>1111 |
2 | 11111111<Tab>1 | 11111111<8 Пробелов>1 |
3 | <Tab>1 | <8 Пробелов>1 |
Выводы:
Составленная процедура работает верно.