Вопрос № 181166: Здравствуйте, уважаемые эксперты! Прошу Вас помочь с решением следующей задачи: Разработать две подпрограммы, одна из которых сравнивает две строки по лексикографическому порядку, а другая обменивает значения двух строк. Разработать программу,...
Вопрос № 181161: Здравствуйте, уважаемые эксперты! Прошу Вас помочь с решением следующей задачи: Разработать две подпрограммы, одна из которых соединяет две строки в одну, а другая обрезает строки до заданной длины (или дополняет пробелами, если длина строки...
Вопрос № 181162: Здравствуйте, уважаемые эксперты! Прошу Вас помочь с решением следующей задачи: Посчитать за какое время процессор выполнит 1 000 000 команд mov DI, SI; add DI, SI; mul SI. Для подсчёта времени использовать вектор 1Ch. Выводить на экран прео...
Вопрос № 181166:
Здравствуйте, уважаемые эксперты! Прошу Вас помочь с решением следующей задачи:
Разработать две подпрограммы, одна из которых сравнивает две строки по лексикографическому порядку, а другая обменивает значения двух строк. Разработать программу, которая вводит с клавиатуры несколько строк (конец ввода пустая строка) и сортирует их в лексикографическом порядке.
Для решения использовать Tasm без использования директивы model, операционная система ДОС, формат ЕХЕ. Приложите к решению пожалуйста
блок-схему.
Отвечает Лысков Игорь Витальевич (Старший модератор) :
Здравствуйте, 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 ;ждем строку
;скопируем в массив строк 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
Ответ отправил: Лысков Игорь Витальевич (Старший модератор)
Ответ отправлен: 08.12.2010, 17:50
Номер ответа: 264594 Украина, Кировоград Тел.: +380957525051 ICQ # 234137952 Mail.ru-агент: igorlyskov@mail.ru
Оценка ответа: 5
Вам помог ответ? Пожалуйста, поблагодарите эксперта за это! Как сказать этому эксперту "спасибо"?
Отправить SMS#thank 264594
на номер 1151 (Россия) |
Еще номера »
Вопрос № 181161:
Здравствуйте, уважаемые эксперты! Прошу Вас помочь с решением следующей задачи:
Разработать две подпрограммы, одна из которых соединяет две строки в одну, а другая обрезает строки до заданной длины (или дополняет пробелами, если длина строки меньше заданной). Разработать программу, которая вводит с клавиатуры число N, затем вводит несколько строк (конец ввода пустая строка) и формирует новую строку, состоящую из первых N символов каждой введённой строки.
Для решения использовать Tasm без использования
директивы model, операционная система ДОС, формат ЕХЕ. Приложите к решению пожалуйста блок-схему.
Отвечает Лысков Игорь Витальевич (Старший модератор) :
Здравствуйте, 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 ;сохраним
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
Ответ отправил: Лысков Игорь Витальевич (Старший модератор)
Ответ отправлен: 08.12.2010, 12:05
Номер ответа: 264588 Украина, Кировоград Тел.: +380957525051 ICQ # 234137952 Mail.ru-агент: igorlyskov@mail.ru
Оценка ответа: 5 Комментарий к оценке: Отлично! :)
Вам помог ответ? Пожалуйста, поблагодарите эксперта за это! Как сказать этому эксперту "спасибо"?
Отправить SMS#thank 264588
на номер 1151 (Россия) |
Еще номера »
Вопрос № 181162:
Здравствуйте, уважаемые эксперты! Прошу Вас помочь с решением следующей задачи:
Посчитать за какое время процессор выполнит 1 000 000 команд mov DI, SI; add DI, SI; mul SI. Для подсчёта времени использовать вектор 1Ch. Выводить на экран преобразованное в ASCII коды число тиков таймера, затраченное на операцию.
Для решения использовать Tasm без использования директивы model, операционная система ДОС, формат ЕХЕ. Приложите к решению пожалуйста блок-схему.
Отвечает Лысков Игорь Витальевич (Старший модератор) :
Здравствуйте, 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 (Россия) |
Еще номера »
Оценить выпуск »
Нам очень важно Ваше мнение об этом выпуске рассылки!
* Стоимость одного СМС-сообщения от 7.15 руб. и зависит от оператора сотовой связи.
(полный список тарифов)
** При ошибочном вводе номера ответа или текста #thank услуга считается оказанной, денежные средства не возвращаются.
*** Сумма выплаты эксперту-автору ответа расчитывается из суммы перечислений на портал от биллинговой компании.