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

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


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

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

Лучшие эксперты данной рассылки

Boriss
Статус: Академик
Рейтинг: 2594
∙ повысить рейтинг »
Абаянцев Юрий Леонидович aka Ayl
Статус: Профессионал
Рейтинг: 2162
∙ повысить рейтинг »
vladisslav
Статус: 8-й класс
Рейтинг: 1324
∙ повысить рейтинг »

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

Номер выпуска:1398
Дата выхода:13.12.2010, 18:30
Администратор рассылки:Лысков Игорь Витальевич (Старший модератор)
Подписчиков / экспертов:224 / 66
Вопросов / ответов:3 / 3

Вопрос № 181166: Здравствуйте, уважаемые эксперты! Прошу Вас помочь с решением следующей задачи: Разработать две подпрограммы, одна из которых сравнивает две строки по лексикографическому порядку, а другая обменивает значения двух строк. Разработать программу,...


Вопрос № 181161: Здравствуйте, уважаемые эксперты! Прошу Вас помочь с решением следующей задачи: Разработать две подпрограммы, одна из которых соединяет две строки в одну, а другая обрезает строки до заданной длины (или дополняет пробелами, если длина строки...
Вопрос № 181162: Здравствуйте, уважаемые эксперты! Прошу Вас помочь с решением следующей задачи: Посчитать за какое время процессор выполнит 1 000 000 команд mov DI, SI; add DI, SI; mul SI. Для подсчёта времени использовать вектор 1Ch. Выводить на экран прео...

Вопрос № 181166:

Здравствуйте, уважаемые эксперты! Прошу Вас помочь с решением следующей задачи:

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

Для решения использовать Tasm без использования директивы model, операционная система ДОС, формат ЕХЕ. Приложите к решению пожалуйста блок-схему.

Отправлен: 08.12.2010, 16:04
Вопрос задал: Ivan Afonin (Посетитель)
Всего ответов: 1
Страница вопроса »


Отвечает Лысков Игорь Витальевич (Старший модератор) :
Здравствуйте, Ivan Afonin!
Вот и программа
Место под строки выделяем в конце, за кодовым сегментом и данными
Ограничиваемся 80 байтами на строку.
Сначала "накидываем" строки, потом сортируем методом пузырька
Обмен решил сделать очень просто: меняем все 80 байт...
Ну и выводим отсортированные строки.

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

.186 ;чтобы можно было использовать push <число>
assume cs:code, ds:data, es:data
code segment para public 'code'
start:
mov ax, data
mov ds, ax
mov es, ax ;пусть es=ds=data

mov N, 0 ;число строк
GetStrLoop: ;цикл ввода строк
lea dx, sString
mov ah, 9
int 21h ;ждем строку

lea dx, bNum
mov ah, 0ah
int 21h ;вводим строку

xor bx, bx
mov bl, bCount ;длина введенной строки, одновременно, смещение конца строки

test bx, bx ;= 0 -> пустая строка
jz Sort ;на сортировку

mov bBuf[bx], 0 ;вставим в конце строки код 0

;скопируем в массив строк
mov ax, 80 ;длина одного элемента массива
mul N ;индекс элемента массива
mov di, ax ;смещение в массиве
lea si, bBuf ;введенная строка
CopyLoop:
lodsb
mov bStr[di], al
inc di
cmp al, 0
jne CopyLoop ;копируем с завершующим нулем
inc N ;считаем строки - элементы массива
mov al, 0ah ;переход на следующую строку
int 29h
jmp GetStrLoop ;и на ввод слежующей строки

Sort: ;сортировка
mov cx, N ;число сортируемых строк
dec cx ;число сравнений
xor si, si ;индекс строки в массиве
SortLoop: ;цикл по поиску очередного минимального
lea di, [si+1] ;начинаем со следующей
push cx ;сохраним счетчик
SearchMinLoop: ;цикл по всем последующим
;сравниваем текущий со всеми последующими
push di ;индекс последующей
push si ;индекс текущей
call StrCompare ;сравниваем
jbe SortNext ;если меньше или равно, то обходим обмен
;меняем местами строки
push di ;индекс последующей
push si ;индекс текущей
call StrChange ;по адресу [si] новая минимальная
SortNext:
inc di ;на следующую последующую
loop SearchMinLoop
inc si ;на следующую текущую
pop cx ;восстановим счетчик сравнений
loop SortLoop

;выводим
lea dx, sResult
mov ah, 9
int 21h

mov cx, N ;число строк
lea bx, bStr ;начало строк
StrLoop:
mov si, bx ;начало текущей строки
add bx, 80 ;для следующей строки
PrintLoop:
lodsb ;очередной символ
cmp al, 0 ;признак конца
je Next
int 29h ;выводим
jmp PrintLoop
Next:
mov al, 0dh ;перевод строки
int 29h
mov al, 0ah
int 29h
loop StrLoop ;по всем

lea dx, sPress ;выведем приглашение нажать на любую клавишу
mov ah, 9
int 21h

mov ah, 0 ;ждем
int 16h

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

;сравнение строк
;параметры подпрограммы
num1 equ word ptr [bp+4] ;индекс первой строки
num2 equ word ptr [bp+6] ;индекс второй строки
StrCompare proc
push bp ;сохраним старый bp
mov bp, sp ;будем адресовать параметры в стеке
push si di ;сохраним используемые регистры
mov ax, 80 ;преобразуем индекс строки в смещение в массиве строк
mul num1
mov si, ax ;смещение первой
mov ax , 80
mul num2
mov di, ax ;смещение второй
CmpLoop:
mov al, bStr[si] ;очередной символ из первой строки
cmp al, bStr[di ] ;сравниваем с символом второй строки
jne StrCmpRet ;не равно - на выход
inc di
inc si ;инкремент смещений
cmp al, 0 ;сравниваем на конец строки
jne CmpLoop ;если не 0, то продолжаем сравнивать
StrCmpRet: ;результат во флагах
pop di si ;восстанавливаем регистры
pop bp
ret 4 ;убираем параметры
StrCompare endp

;обмен строк, меняем, не мудствуя лукаво, все 80 байт :)
;параметры подпрограммы
num1 equ word ptr [bp+4] ;индекс первой строки
num2 equ word ptr [bp+6] ;индекс второй строки
StrChange proc
push bp ;сохраним старый bp
mov bp, sp ;будем адресовать параметры в стеке
push cx si di ;сохраним используемые регистры
mov ax, 80 ;преобразуем индекс строки в смещение в массиве строк
mul num1
mov si, ax ;смещение первой
mov ax, 80
mul num2
mov di, ax ;смещение второй
mov cx, 40 ;число слов (80/2)
ChgLoop:
mov ax, word ptr bStr[si] ;обмениваем по словам
xchg ax, word ptr bStr[di]
mov word ptr bStr[si], ax
inc si ;смещение на следующие слова
inc si
inc di
inc di
loop ChgLoop ;по всем 40 словам
pop di si cx
pop bp
ret 4
StrChange endp

code ends

data segment para public 'data'
N dw 0 ;число строк
sString db 'Enter string: $'
sResult db 0ah,0ah,'Sorted strings: ',0dh,0ah,'$'
sPress db 0dh,0ah,'Press any key$'
;буфер для ввода строки (для функции 0ah)
bNum db 80 ;максимальный размер буфера
bCount db ? ;реальный размер строки
bBuf db 80 dup (?) ;сама строка
bStr label byte ;адрес в конце программы для хранения строк
data ends

end start


181166-block-sch.doc (55.0 кб)
-----
Люби своего ближнего, как самого себя

Ответ отправил: Лысков Игорь Витальевич (Старший модератор)
Ответ отправлен: 08.12.2010, 17:50
Номер ответа: 264594
Украина, Кировоград
Тел.: +380957525051
ICQ # 234137952
Mail.ru-агент: igorlyskov@mail.ru

Оценка ответа: 5

Вам помог ответ? Пожалуйста, поблагодарите эксперта за это!
Как сказать этому эксперту "спасибо"?
  • Отправить SMS #thank 264594 на номер 1151 (Россия) | Еще номера »
  • Отправить WebMoney:


  • Вопрос № 181161:

    Здравствуйте, уважаемые эксперты! Прошу Вас помочь с решением следующей задачи:

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

    Для решения использовать Tasm без использования директивы model, операционная система ДОС, формат ЕХЕ. Приложите к решению пожалуйста блок-схему.

    Отправлен: 08.12.2010, 10:09
    Вопрос задал: Ivan Afonin (Посетитель)
    Всего ответов: 1
    Страница вопроса »


    Отвечает Лысков Игорь Витальевич (Старший модератор) :
    Здравствуйте, Ivan Afonin!
    Программа приведена ниже.
    Единственное замечание, которое хочу сделать:
    Результирующую строку, куда мы пишем результат работы программы (склеянные усеченные подстроки)
    я задаю после программы и данных. Т.о. длина может быть практически любой.
    Код:
    ;Разработать две подпрограммы, одна из которых соединяет две строки в одну, 
    ;а другая обрезает строки до заданной длины (или дополняет пробелами,
    ;если длина строки меньше заданной). Разработать программу, которая
    ;вводит с клавиатуры число N, затем вводит несколько строк
    ;(конец ввода пустая строка) и формирует новую строку,
    ;состоящую из первых N символов каждой введённ ой строки.

    .186 ;чтобы можно было использовать push <число>
    assume cs:code, ds:data, es:data
    code segment para public 'code'
    start:
    mov ax, data
    mov ds, ax
    mov es, ax ;пусть es=ds=data

    lea dx, sNum
    mov ah, 9
    int 21h ;ждем число N

    mov bNum, 80 ;задаем максимальное значение строки
    lea dx, bNum
    mov ah, 0ah
    int 21h ;вводим числовую строку

    lea si, bBuf ;строка
    call stoi ;преобразовываем в число
    mov N, ax ;сохраним

    mov bResult, 0 ;пустая строка

    MainLoop: ;цикл ввода строк
    lea dx, sString
    mov ah, 9
    int 21h ;ждем строку

    lea dx, bNum
    mov ah, 0ah
    int 21h ;вводим строку

    xor bx, bx
    mov bl, bCount ;длина введенной строки, одновременно, смещение конца строки

    test bx, bx ;= 0 -> пустая строка
    jz PrintResult ;на вывод результирующей строки

    mov bBuf[bx], 0 ;вставим в конце строки код 0

    push N ;заданна я длина
    push offset bBuf ;адрес введенной строки
    call Trunc ;обрежем до заданной длины

    push offset bBuf ;адрес введенной строки
    push offset bResult ;адрес результирующей строки
    call StrCat ;склеим
    jmp MainLoop ;на повтор

    PrintResult:
    lea dx, sResult
    mov ah, 9
    int 21h ;выведем сообщение о результате

    lea si, bResult ;результирующая строка
    PrintLoop:
    lodsb ;очередной символ
    cmp al, 0 ;признак конца
    je Exit
    int 29h ;выводим
    jmp PrintLoop

    Exit:
    lea dx, sPress ;выведем приглашение нажать на любую клавишу
    mov ah, 9
    int 21h

    mov ah, 0 ;ждем
    int 16h

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

    stoi proc ;преобразование строки [si] в число AX
    xor bx, bx ;здесь будем стоить число
    xor cx, cx ;счетчик разрядов
    stoi_next:
    lodsb ;очередной символ
    cmp al, 0dh ;конец стоки?
    je stoi_eol
    cmp al, '0'
    jb stoi_sep ;любая нецифр а - разделитель
    cmp al, '9'
    ja stoi_sep
    push ax ;сохраним новый разряд
    mov ax, 10
    mul bx ;умножим старшие на 10
    pop dx ;новый
    and dx, 0fh ;'0'-'9' -> 0-9
    add ax, dx ;добавляем новый разряд
    mov bx, ax ;сохраняем
    inc cx ;считаем
    jmp stoi_next ;продолжаем
    stoi_sep: ;встретили разделитель
    jcxz stoi_next ;были только разделители - на продолжение
    ; иначе - конец числа и выходим
    stoi_eol: ; если числа нет и встретили 0dh - конец строки
    mov ax, bx ;число возвращаем в ax
    ret
    stoi endp

    ;обрезка строки
    ;параметры подпрограммы
    pStr equ [bp+4] ;адрес строки
    num equ [bp+6] ;число оставляемых символов
    Trunc proc
    push bp ;сохраним старый bp
    mov bp, sp ;будем адресовать параметры в стеке
    mov di, pStr ;адрес строки
    mov cx, num ;число оставляемых символов
    TruncLoop:
    mov al, [di]
    inc di
    cmp al, 0 ;проверим на конец строки
    l oopnz TruncLoop ;выходим из цикла, когда cx==0 или FZ==1
    jnz TruncZero ;если FZ==0, то введенная строка больше числа num - усекаем
    TruncSpace: ;если FZ==1, то встретили раньше времени 0 - дополним пробелами
    inc cx ;подправим cx, уменьшенное лишний раз командой loopnz
    dec di ;и di, увеличенное inc-ом
    mov al, ' ' ;дополним пробелами
    rep stosb ;cx раз
    TruncZero:
    mov byte ptr [di],0 ;закроем строку 0
    pop bp ;восстановим bp
    ret 4 ;уберем из стека параметры
    Trunc endp

    ;склеивание двух строк
    ;параметры подпрограммы
    pStrOut equ [bp+4] ;адрес, куда доклеиваем
    pStrIn equ [bp+6] ;адрес, что доклеиваем
    StrCat proc
    push bp ;сохраним старый bp
    mov bp, sp ;будем адресовать параметры в стеке
    mov di, pStrOut ;адрес выходной строки
    mov al, 0 ;найдем символ - конец строки
    mov cx, 0ffffh ;заведомо большое число
    repne scasb ;ищем конец строки
    dec di ;вернем di на позицию нуля
    mov si, pStrIn ;адрес исходной строки
    CatLoop:
    lodsb ;читаем символ исходной строки
    stosb ;копируем
    cmp al, 0 ;дошли до конца ?
    jne CatLoop
    pop bp ;восстановим bp
    ret 4 ;уберем из стека параметры
    StrCat endp

    code ends

    data segment para public 'data'
    sNum db 'Enter N: $'
    sString db 0ah,'Enter string: $'
    sResult db 0ah,'Result string: $'
    sPress db 0dh,0ah,'Press any key$'
    ;буфер для ввода числовой строки (для функции 0ah)
    bNum db ? ;максимальный размер буфера
    bCount db ? ;реальный размер строки
    bBuf db 80 dup (?) ;сама строка
    N dw ? ;"водораздел" количества символов
    bResult label byte ;адрес в конце программы для формирования
    ; результирующей строки
    data ends

    end start


    181161-block-sch.doc (50.0 кб)
    -----
    Люби своего ближнего, как самого себя

    Ответ отправил: Лысков Игорь Витальевич (Старший модератор)
    Ответ отправлен: 08.12.2010, 12:05
    Номер ответа: 264588
    Украина, Кировоград
    Тел.: +380957525051
    ICQ # 234137952
    Mail.ru-агент: igorlyskov@mail.ru

    Оценка ответа: 5
    Комментарий к оценке:
    Отлично! :)

    Вам помог ответ? Пожалуйста, поблагодарите эксперта за это!
    Как сказать этому эксперту "спасибо"?
  • Отправить SMS #thank 264588 на номер 1151 (Россия) | Еще номера »
  • Отправить WebMoney:


  • Вопрос № 181162:

    Здравствуйте, уважаемые эксперты! Прошу Вас помочь с решением следующей задачи:

    Посчитать за какое время процессор выполнит 1 000 000 команд mov DI, SI; add DI, SI; mul SI. Для подсчёта времени использовать вектор 1Ch. Выводить на экран преобразованное в ASCII коды число тиков таймера, затраченное на операцию.

    Для решения использовать Tasm без использования директивы model, операционная система ДОС, формат ЕХЕ. Приложите к решению пожалуйста блок-схему.

    Отправлен: 08.12.2010, 10:28
    Вопрос задал: Ivan Afonin (Посетитель)
    Всего ответов: 1
    Страница вопроса »


    Отвечает Лысков Игорь Витальевич (Старший модератор) :
    Здравствуйте, Ivan Afonin!
    Программа готова.
    Увеличил число выполнения цикла до 100 000 000. Иначе, выходит слишком быстро.
    А так - порядка секунды...

    181162-block-sch.doc (42.0 кб)
    В блок-схеме счетчик отработки фрагмента для наглядности я сделал, как одну переменную "Счетчик"
    Хотя там, на самом деле, два вложенных цикла
    Код:
    ;Посчитать за какое время процессор выполнит 1 000 000 команд 
    ;mov DI, SI
    ;add DI, SI
    ;mul SI
    ;Для подсчёта времени использовать вектор 1Ch.
    ;Выводить на экран преобразованное в ASCII коды число тико в таймера,
    ;затраченное на операцию.

    .186 ;чтобы можно было использовать push <число>
    assume cs:code, ds:data
    code segment para public 'code'
    start:
    mov ax, 351ch
    int 21h ;узнаем вектор 1ch в es:bx

    mov ax, data
    mov ds, ax ;ds = data

    mov Off_1c, bx ;сохраним старый адрес в сегменте данных
    mov Seg_1c, es

    lea dx, new_1c ;установим новый адрес
    push cs ;обработчика прерывания 1ch
    pop ds ;ds:dx
    mov ax, 251ch
    int 21h

    mov ax, data
    mov ds, ax ;ds = data

    mov si, 123 ;что-нибудь, чтобы что-то там считало :)
    mov bx, Ticks ;сохраним значение счетчика тиков в bx
    mov cx, 10000 ;будем считать 10000 * 10000 = 100 000 000 циклов
    Loop_1:
    push cx
    mov cx, 10000
    Loop_2:
    mov di, si ;тестовые команды
    add di, si
    mul si

    loop Loop_2
    pop cx
    loop Loop_1

    mov ax, Ticks ;новое число тиков
    sub ax, bx ;число затраченных тиков

    push ax ds ;сохраним ax и ds
    lds dx, dword ptr Off_1c ;ds:dx - адрес старого вектора
    mov ax, 251ch
    int 21h ;восстановим!
    pop ds ;ds = data

    lea dx, sTicks ;выведем пояснение
    mov ah, 9
    int 21h

    pop ax ;число тиков
    call PutNumber ;выведем
    Exit:
    lea dx, sPress ;выведем приглашение нажать на любую клавишу
    mov ah, 9
    int 21h

    mov ah, 0 ;ждем
    int 16h

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

    PutNumber proc ;преобразование числа из ax в строку и вывод на экран
    xor cx, cx ;счетчик разрядов
    mov bx, 10 ;делим на 10
    DivLoop: ;цикл преобразования в разряды
    cwd ;подготавливаем dx:ax к делению
    idiv bx ;dx = очередному младшему разряду
    push dx ;сохраним в стеке
    inc cx ;считаем
    test ax, ax ;продолжаем, пока не дойдем до 0
    jnz DivLoop
    PrLoop: ;цикл вывода в обратном порядке
    pop ax ;берем число 0-9 из стека
    or al, '0' ;преобразовывае м в символ '0'-'9'
    int 29h ;выводим
    loop PrLoop
    ret
    PutNumber endp

    new_1c: ;подпрограмма отработки 1ch
    push ds ;сохраним ds
    push data
    pop ds ;ds = data
    inc Ticks ;инкремент Ticks в сегменте данных!
    pushf ;вызовем старый обработчик, сначала надо pushf, т.к. выход по iret!
    call dword ptr Off_1c;адрес в переменной в сегменте данных
    pop ds ;восстановим ds
    iret ;возврат из прерывания
    code ends

    data segment para public 'data'
    Off_1c dw 0 ;смещение старого вектора 1c
    Seg_1c dw 0 ;сегмент старого вектора 1c
    Ticks dw 0 ;счетчик имков таймера
    sTicks db 'Ticks count = $'
    sPress db 0dh,0ah,'Press any key$'
    bStr db 16 dup (?) ;строка для формирования числовой строки
    data ends

    end start

    -----
    Люби своего ближнего, как самого себя

    Ответ отправил: Лысков Игорь Витальевич (Старший модератор)
    Ответ отправлен: 08.12.2010, 14:30
    Номер ответа: 264591
    Украина, Кировоград
    Тел.: +380957525051
    ICQ # 234137952
    Mail.ru-агент: igorlyskov@mail.ru

    Вам помог ответ? Пожалуйста, поблагодарите эксперта за это!
    Как сказать этому эксперту "спасибо"?
  • Отправить SMS #thank 264591 на номер 1151 (Россия) | Еще номера »
  • Отправить WebMoney:


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

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

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

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

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

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

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


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

    В избранное