Хостинг портала RFpro.ru: Московский хостер Профессиональный ХОСТИНГ на базе Linux x64 и Windows x64 РАССЫЛКИ ПОРТАЛА RFPRO.RU Чемпионы рейтинга экспертов в этой рассылке Номер выпуска: | 1334 | Дата выхода: | 11.05.2010, 10:30 | Администратор рассылки: | Лысков Игорь Витальевич, Модератор | Подписчиков / экспертов: | 280 / 60 | Вопросов / ответов: | 2 / 2 | IRC-канал по теме: | #assembler | Вопрос № 178138: Доброго времени суток дорогие эксперты: Требуется с помощью TASM организовать решение задачи: Есть ли в данной строке слова, множества символов которых равны. Хар-ки: 1) процессор intel core 2 solo CPU U3500 2) window vista home pr... Вопрос № 178214: Здравствуйте, помогите дописать программу на МАSМе, нужно вывести результат арифметического выражения : (a+b)/(c+d). моя программа выводит правильный результат если ответ положительный , если же он отрицательный то получается неправильный ответ , и е... Вопрос № 178138: Доброго времени суток дорогие эксперты: Требуется с помощью TASM организовать решение задачи: Есть ли в данной строке слова, множества символов которых равны.
Хар-ки: 1) процессор intel core 2 solo CPU U3500 2) window vista home premium 32х разрядная 3) Turbo Assembler Version 4.1 в папке asm находится файл TASM поэтому думаю он предпочтителен 4) вычисления производить в сопроцессоре
Строку желательно вводить с клавиатуры. Отправлен: 01.05.2010, 10:01 Вопрос задал: Юдин Евгений Сергеевич, 1-й класс Всего ответов: 1 Страница вопроса » Отвечает Лысков Игорь Витальевич, Модератор : Здравствуйте, Юдин Евгений Сергеевич. Вот Вам программа. Думаю, комментарии в тексте помогут Вам разобраться
Код: .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 ;количество ca ll 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 c x ;восстановим регистры 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 ;конец программы
----- Удачи! Ответ отправил: Лысков Игорь Витальевич, Модератор Ответ отправлен: 05.05.2010, 15:41 Номер ответа: 261213 Украина, Кировоград Тел.: +380957525051 ICQ # 234137952 Mail.ru-агент: igorlyskov@mail.ru Абонент Skype: igorlyskov Вам помог ответ? Пожалуйста, поблагодарите эксперта за это! Как сказать этому эксперту "спасибо"? | Отправить SMS #thank 261213 на номер 1151 (Россия) | Еще номера » | Вопрос № 178214: Здравствуйте, помогите дописать программу на МАSМе, нужно вывести результат арифметического выражения : (a+b)/(c+d). моя программа выводит правильный результат если ответ положительный , если же он отрицательный то получается неправильный ответ , и ещё отдельно нужно вывести остаток если не делится нацело... Отправлен: 05.05.2010, 13:27 Вопрос задал: Faraon, Посетитель Всего ответов: 1 Страница вопроса » Отвечает Лысков Игорь Витальевич, Модератор : Здравствуйте, Faraon. Ваша ошибка была в том, что формат "%d" подразумевает двойное слово! А не слово, как у Вас. Программы под Windows 32-битные! Для формата short надо было использовать "%hd". Кроме того, почему Вы не пользуетесь возможностями 32-битного процессора? Например, можно было сделать (под 32-битные регистры, но можно так и с 16-битными) так:
Код: movsx ebx, d movsx eax, k add ebx, eax jz label1 movsx ecx, a movsx eax, b add eax, ecx cdq idiv ebx
И так далее... но это так, к слову...
Код: .386 .model flat, stdcall
include \masm32\include\user32.inc include \masm32\include\kernel32.inc includelib \masm32\lib\user32.lib includelib \masm32\lib\kernel32.lib includelib \masm32\lib\masm32.lib
.data Lab_Caption db "Lab8!",0 Print_Mask db "%hd",0 ;у нас слово, а не двойное слово!!! Print_Mask2 db " %hd",0 Print_Mess DB "The result is: " Print_Buff db 16 dup (0) ;увеличим буфер Chars_Number dd ?
a db 127 b db -27 k db 10 d db -16 rez dw 0 tail dw 0
.code main: call AllocConsole or EAX,EAX jz fail
push offset Lab_Caption call SetConsoleTitleA or EAX,EAX jz fail
sub dx,dx sub ax,ax mov al,d cbw mov bx,ax mov al,k cbw add bx,ax ;bx=c+d mov al,a cbw mov cx,ax mov al,b cbw add ax,cx ;ax=a+b cmp bx ,0 je label1 idiv bx cbw mov rez,ax ;лучше так, а не add mov tail,dx ;остаток
label1 : push DWORD ptr rez push offset Print_Mask push offset Print_Buff call wsprintf add SP,12
cmp tail, 0 ;если остаток не 0, то добавим и его je print_message
;вычислим адрес, куда запишем остаток push offset Print_Mess call lstrlen ;длина строки add eax, offset Print_Mess
push DWORD ptr tail ;остаток, отделенный двумя пробелами push offset Print_Mask2 push eax ;адрес call wsprintf add SP,12
print_message: push -11 call GetStdHandle mov esi, eax ;сохраним handle push offset Print_Mess call lstrlen ;считаем длину сообщения
push 0 push offset Chars_Number push eax ;длина push offset Print_Mess push esi ;handle call WriteConsoleA
push -10 call GetStdHandle
push 0 push offset Chars_N umber push 1 push offset Print_Buff push EAX call ReadConsoleA
fail: push 0 call ExitProcess
end main ----- Удачи! Ответ отправил: Лысков Игорь Витальевич, Модератор Ответ отправлен: 06.05.2010, 13:25 Номер ответа: 261238 Украина, Кировоград Тел.: +380957525051 ICQ # 234137952 Mail.ru-агент: igorlyskov@mail.ru Абонент Skype: igorlyskov
Оценка ответа: 5 Вам помог ответ? Пожалуйста, поблагодарите эксперта за это! Как сказать этому эксперту "спасибо"? | Отправить SMS #thank 261238 на номер 1151 (Россия) | Еще номера » | Оценить выпуск » Нам очень важно Ваше мнение об этом выпуске рассылки! Скажите "спасибо" эксперту, который помог Вам! Отправьте СМС-сообщение с тестом #thank НОМЕР_ОТВЕТА на короткий номер 1151 (Россия) Номер ответа и конкретный текст СМС указан внизу каждого ответа. Полный список номеров » * Стоимость одного СМС-сообщения от 7.15 руб. и зависит от оператора сотовой связи. (полный список тарифов) ** При ошибочном вводе номера ответа или текста #thank услуга считается оказанной, денежные средства не возвращаются. *** Сумма выплаты эксперту-автору ответа расчитывается из суммы перечислений на портал от биллинговой компании. |
Комментариев нет:
Отправить комментарий