Консультация № 178138
01.05.2010, 10:01
0.00 руб.
05.05.2010, 10:48
0 1 1
Доброго времени суток дорогие эксперты:
Требуется с помощью TASM организовать решение задачи:
Есть ли в данной строке слова, множества символов которых равны.

Хар-ки:
1) процессор intel core 2 solo CPU U3500
2) window vista home premium 32х разрядная
3) Turbo Assembler Version 4.1 в папке asm находится файл TASM поэтому думаю он предпочтителен
4) вычисления производить в сопроцессоре

Строку желательно вводить с клавиатуры.

Обсуждение

давно
Посетитель
7438
7205
05.05.2010, 15:41
общий
это ответ
Здравствуйте, Юдин Евгений Сергеевич.
Вот Вам программа.
Думаю, комментарии в тексте помогут Вам разобраться
Код:

.286

cseg segment para public 'code'
assume cs:cseg, ds:dseg, es:dseg
start: ;точка входа
mov ax, dseg ;настроим сегментные регистры
mov ds, ax
mov es, ax

lea dx, sPrompt ;подсказка для ввода строки
mov ah, 9
int 21h

lea dx, max ;вводим максимум 64 символа
mov ah, 0ah
int 21h

call strstr ;строим массив адресов слов
call analysis ;анализируем, считаем и выводим

lea dx, sTotal ;выведем число найденных пар слов
mov ah, 9
int 21h

mov ax, ecount ;количество
call PrDec ;выведе десятичное число

lea dx, sPairs ;закончим сообщение
mov ah, 9
int 21h

mov ah, 0 ;ждем нажатие на клавишу
int 16h

mov ax, 4c00h ;выход в ДОС
int 21h

;строим массив адресов слов
strstr proc
lea si, string-1 ;адрес введеной строки -1 (после inc si будет начало)
lea bx, addrs ;здесь будем хранить адреса слов
mov wcount, 0 ;число слов
mov ah, 0 ;признак, что ждем, ah=0 - разделитель, ah=1 слово
str_loop: ;цикл по всем символам строки
inc si ;на следующий символ
mov al, [si] ;читаем очередной символ
cmp al, 0dh ;конец строки?
je str_ret ;на выход
lea di, separ ;проверим, разделитель?
mov cx, len_sep ;число возможных разделителей
repne scasb ;ищем...
jz str_sep ;нашли - разделитель
cmp ah, 1 ;если во вводе слова, то на следующий символ
je str_loop
inc wcount ;получили начало нового слова, считаем
mov ah, 1 ;признак слова
mov [bx], si ;запоминаем начало слова
lea bx, [bx+2] ;подготавливаем адрес для сохранения адреса след слова
jmp str_loop ;на ввод очередного символа
str_sep: ;встретили разделитель
cmp ah, 0 ;если ожидали разделитель,
je str_loop ; то уходим на ввод очередного символа
mov ah, 0 ;признак разделителя
mov byte ptr [si], 0 ;закрываем слово нулем
jmp str_loop ;на ввод очередного символа
str_ret:
mov byte ptr [si], 0 ;на всякий случай, закрываем последнее слово нулем
ret ; (возможно, оно уже было закрыто)
strstr endp

;сравниваем два слова [si] и [di] на совпадение множеств символов
;будем искать за два прохода:
;1) каждый символ в [si] ищем в [di]
;2) каждый символ в [di] ищем в [si]
;результат: ZF=1 - множества совпадают, ZF=0 - не совпадают
Compare proc
push cx si di ;сохраним регистры
mov cx, 2 ;будем искать за два прохода
cmp_loop_1: ;цикл по символам первого слова
lodsb ;очередной
cmp al, 0 ;дошли до конца?
je cmp_back ;на следующий проход или выход
push di ;сохраним адрес второго слова
cmp_loop_2: ;цикл по всем символам второго слова
scasb ;сравниваем al и es:[di], di=di+1
je cmp_found ;равно?
cmp byte ptr [di-1], 0 ;если не равно и не дошли до конца второй строки
jne cmp_loop_2 ; то на следующий символ второй строки
pop di ;не нашли! восстанавливаем di
or al, 1 ;сбрасываем флаг ZF - признак несовпадения множеств
jmp cmp_ret ;на выход
cmp_found: ;нашли...
pop di ;восстанавливаем di
jmp cmp_loop_1 ;на поиск следующего символа первого слова во втором слове
cmp_back: ;очередной проход дал совпадение!
pop si di ;поменяем местами адреса строка и пройдем еще раз!
push si di ;загоним в стек для корректного выхода
loop cmp_loop_1 ;на следующий проход или выход
cmp_ret: ;сюда попадем при ZF=1 и множества равны!
pop di si cx ;восстановим регистры
ret
Compare endp

;выведем результат
Print proc
push si ;сохраним si
cmp ecount, 0 ;выведем заголовок только в самом начале!
jne pr_1_loop
lea dx, sWords ;заголовок
mov ah, 9
int 21h
pr_1_loop: ;выведем первое слово
lodsb
cmp al, 0
je Pr_space
int 29h
jmp pr_1_loop
Pr_space:
mov al, ' ' ;отделим пробелом
int 29h
mov si, di ;выведем второе слово
pr_2_loop:
lodsb
cmp al, 0
je Pr_ret
int 29h
jmp pr_2_loop
Pr_ret:
mov al, 0dh ;перейдем на новую строку
int 29h
mov al, 0ah
int 29h
inc ecount ;посчитаем
pop si
ret
Print endp

;проанализируем строки
analysis proc
mov ecount, 0 ;счетчик равных пар
mov cx, wcount ;счетчик слов
jcxz an_ret ;для 0 нечего делать
lea bx, addrs ;адрес массива адресов слов
jmp an_next_1 ;на проверку количества первых слов
an_loop_1: ;цикл первого слова
mov si, [bx] ;адрес первого слова
lea bx, [bx+2] ;на следующий адрес
mov bp, bx ;сохраним как начало массива вторых слов
push cx ;сохраним счетчик
jmp an_next_2 ;на проверку количества вторых слов
an_loop_2: ;цикл второго слова
mov di, ds:[bp] ;адрес второго слова
lea bp, [bp+2] ;на следующий адрес
call Compare ;сравниваем!
jnz an_next_2 ;если неравно, то на адрес следующего второго слова
call Print ;равно - посчитаем и выведем на экран
an_next_2:
dec cx ;циклим, пока cx>=0
jge an_loop_2
pop cx ;восстановим счетчик аресов первого слова
an_next_1:
loop an_loop_1 ;циклим, пока cx>0
an_ret: ;выходим
ret
analysis endp

;вывод десятичного числа из ax
PrDec proc
mov bx, 10
xor cx, cx
pd_dig: ;цикл формирования цифр,
xor dx, dx ; как остатков от деления на 10
div bx
push dx
inc cx
or ax, ax
jnz pd_dig
pd_pr: ;цикл вывода цифр
pop ax
add al, '0'
int 29h
LOOP pd_pr
ret
PrDec endp

cseg ends


dseg segment para public 'data'
separ db ' ,;:.',9 ;массив разделителей
len_sep equ $-separ

sPrompt db 'Enter string: $'
sWords db 0dh,0ah,'Founded words:',0dh,0ah,'$'
sTotal db 0dh,0ah,'Total $'
sPairs db ' words pair(s)',0dh,0ah
db 'Press any key for exit$'
max db 65 ;максимально возможная длина = 64 (+1 для 0dh)
rcount db 0 ;реальная длина
string db 65 dup (?) ;сама строка
wcount dw 0 ;счетчик слов в строке
ecount dw 0 ;счетчик найденных совпадений множеств символов строк
addrs label word ;адрес для хранения массива адресов строк
dseg ends

end start ;конец программы
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Форма ответа