Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

RFpro.ru: Ассемблер? Это просто! Учимся программировать


Хостинг портала RFpro.ru:
Московский хостер
Профессиональный ХОСТИНГ на базе Linux x64 и Windows x64

РАССЫЛКИ ПОРТАЛА RFPRO.RU

Чемпионы рейтинга экспертов в этой рассылке

Boriss
Статус: Академик
Рейтинг: 2256
∙ повысить рейтинг »
_Ayl_
Статус: Практикант
Рейтинг: 1835
∙ повысить рейтинг »
vladisslav
Статус: 6-й класс
Рейтинг: 1237
∙ повысить рейтинг »

/ КОМПЬЮТЕРЫ И ПО / Программирование / Assembler (Ассемблер)

Номер выпуска: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 (Россия) | Еще номера »
  • Отправить WebMoney:

  • Вопрос № 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 (Россия) | Еще номера »
  • Отправить WebMoney:

  • Оценить выпуск »
    Нам очень важно Ваше мнение об этом выпуске рассылки!

    Задать вопрос экспертам этой рассылки »

    Скажите "спасибо" эксперту, который помог Вам!

    Отправьте СМС-сообщение с тестом #thank НОМЕР_ОТВЕТА
    на короткий номер 1151 (Россия)

    Номер ответа и конкретный текст СМС указан внизу каждого ответа.

    Полный список номеров »

    * Стоимость одного СМС-сообщения от 7.15 руб. и зависит от оператора сотовой связи. (полный список тарифов)
    ** При ошибочном вводе номера ответа или текста #thank услуга считается оказанной, денежные средства не возвращаются.
    *** Сумма выплаты эксперту-автору ответа расчитывается из суммы перечислений на портал от биллинговой компании.


    © 2001-2010, Портал RFpro.ru, Россия
    Авторское право: ООО "Мастер-Эксперт Про"
    Автор: Калашников О.А. | Программирование: Гладенюк А.Г.
    Хостинг: Компания "Московский хостер"
    Версия системы: 2010.6.14 от 03.03.2010

    В избранное