Форум программистов
 
Контакты: о проблемах с регистрацией, почтой и по другим вопросам пишите сюда - alarforum@yandex.ru, проверяйте папку спам! Обязательно пройдите активизацию e-mail.

Вернуться   Форум программистов > Низкоуровневое программирование > Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM
Регистрация

Восстановить пароль
Повторная активизация e-mail


Ответ
 
Опции темы
Старый 05.12.2019, 19:35   #1
Solo_
Новичок
Джуниор
 
Регистрация: 05.12.2019
Сообщений: 2
По умолчанию По пути обучения встретился с данным заданием, не могу придумать принцип решения, может у кого возникнут идеи?

По пути обучения встретился с данным заданием, не могу придумать принцип решения, может у кого возникнут идеи? Я дошел только до принципа полного реверса строки и последующего реверса каждого слова, но организовать его пока не получилось

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

Встречал решения подобных задачек, но так и не смог в них разобраться, так как еще не сильно шарю.
Из уточнений: Должен быть организован ввод(и вывод) через прерывание, именно в командной строке, а не в самом коде, сам код желательно должен быть как можно проще, либо же помогите в последствии мне разобраться во всем.
Solo_ вне форума Ответить с цитированием
Старый 06.12.2019, 08:59   #2
R71MT
Участник клуба
 
Аватар для R71MT
 
Регистрация: 16.06.2011
Сообщений: 1,375
По умолчанию

Цитата:
Сообщение от Solo_ Посмотреть сообщение
либо же помогите в последствии мне разобраться во всем.
так помогают тому, кто сам хоть что-то сделал..
наработки и мысли имеются какие-нибудь?
Нашедшего выход - затаптывают первым..
R71MT вне форума Ответить с цитированием
Старый 06.12.2019, 15:27   #3
Solo_
Новичок
Джуниор
 
Регистрация: 05.12.2019
Сообщений: 2
По умолчанию

Цитата:
Сообщение от R71MT Посмотреть сообщение
так помогают тому, кто сам хоть что-то сделал..
наработки и мысли имеются какие-нибудь?
Вот код не мой, рабочий, но разобраться в нем досконально не получается.

.model small

.stack 200h

.data
DelimChar equ ' ' ;символ, разделитель слов
_STDOUT_ equ 1 ;описатель вывода на экран
;обрабатываемая строка
String db 'loll goog bbooob suup mooling some paper to garbage'
Len dw $-String
;сообщения программы
CrLf db 0Dh, 0Ah, '$'
msgSourceString db 'Instant:', 0Dh, 0Ah, '$'
msgResultString db 'Result:', 0Dh, 0Ah, '$'
.code

Reverse proc
push si
push di
jmp @@next
@@while:
mov al, [si]
mov ah, [di]
mov [di], al
mov [si], ah
inc si
dec di
@@next:
cmp si, di
jb @@while
pop di
pop si
ret
Reverse endp

Show proc
push ax
push bx
push cx
push dx
push si
push di

mov ah, 40h
mov bx, _STDOUT_
mov cx, [Len]
lea dx, [String]
int 21h
mov ah, 09h
lea dx, CrLf
int 21h

pop di
pop si
pop dx
pop cx
pop bx
pop ax
ret
Show endp

main proc
mov ax, @data
mov ds, ax

;вывод исходных данных
mov ah, 09h
lea dx, [msgSourceString]
int 21h
mov ah, 40h
mov bx, _STDOUT_
mov cx, [Len]
lea dx, [String]
int 21h
mov ah, 09h
lea dx, CrLf
int 21h
;обработка строки

lea si, String
mov cx, Len
cld
;реверс всей строки
mov di, si
add di, cx
dec di
call Reverse

@@Loop:
;пропускаем все разделители
@@WhileDelimiter:
lodsb
cmp al, DelimChar
loope @@WhileDelimiter
jcxz @@Finish ;если строка закончилась - выйти
;найдено новое слово
mov di, si ;(di-1) указатель на начало слова
;пропускаем все буквы слова до разделителя
@@WhileWord:
lodsb
cmp al, DelimChar
loopne @@WhileWordт
cmp cx, 1 ;учтём возможный выход из цикла по завершению строки
adc si, 0 ;когда на первый символ слова будет указывать (esi+1)
;теперь слово выделено
;(di-1) - начало слова
;(si-2) - конец слова
sub si, 2
dec di
xchg si, di
call Reverse
xchg si, di
add si, 2

test cx, cx
jnz @@Loop
@@Finish:
;вывод результатов

mov ah, 09h
lea dx, [msgResultString]
int 21h
mov ah, 40h
mov bx, _STDOUT_
mov cx, [Len]
lea dx, [String]
int 21h
mov ah, 09h
lea dx, [CrLf]
int 21h

;завершение программы
mov ax, 4C00h

main endp




Это мой код, но не работает корректно

data segment
IN_STR db 80,?,82 dup(?)
OUT_STR db 80,?,82 dup(?)

data ends
code segment
assume cs: code, ds: data
start:
lea dx,IN_STR
mov ah,0ah
int 21h
xor ah,ah
mov dl,IN_STR+1
lea bx,IN_STR+2
add bl,dl
dec bx
lea si,OUT_STR+2
mov dl,0
mov cx,0
mov di," "
push di

H:
cmp dl,IN_STR+1
je P
jge ex
mov al,[bx]
cmp al," "
jne M
P:
pop cx
mov [Si],cl
inc si
cmp cx," "
je M
loop p

M:
push ax
inc dl
dec bx
loop H

ex:
lea dx,OUT_STR
mov ah,09h
int 21h
lea dx,IN_STR
mov ah,0ah
int 21h


quit:
mov ax, 4c00h
int 21
code ends
end start
Solo_ вне форума Ответить с цитированием
Старый 07.12.2019, 13:48   #4
R71MT
Участник клуба
 
Аватар для R71MT
 
Регистрация: 16.06.2011
Сообщений: 1,375
По умолчанию

Цитата:
Сообщение от Solo_ Посмотреть сообщение
не могу придумать принцип решения, может у кого возникнут идеи?
вариантов тут много, и вот один из них..
Вводишь строку и смещаешься в её конец. Теперь справа-налево ищем пробел, по-ходу считая длину слова. Как найдёшь пробел, ставишь флаг Direction (DF) в прямое направление, и копируешь слово в выходной буфер. Потом опять DF в единицу (обратный шаг), и так по всей строке. Вариант на FASM'e примерно такой (блох не вылавливал, но вроде работает):

Код:
;== fasm code ==
org 100h
jmp start

mes0     db   13,10,'String: $'
mes1     db   13,10,'Result: $'
oldStr   db   80,0,80 dup(0)     ; буфер для fn(0Ah) - строка юзера
newStr   db   80 dup('$')        ; буф под реверс-строку

start:
;- Вводим строку в буфер
       mov    dx,mes0       ; запрос
       mov    ah,9          ;
       int    21h           ;
       mov    ah,0xA        ; ввод fn.0Ah
       mov    dx,oldStr     ;
       int    21h           ;

;- Настраиваем регистры ---------------
       movzx  cx,byte[oldStr+1]  ; СХ = длина введённой строки,
       dec    cx                 ;   ..без символа 0x0D (Enter)
       mov    di,newStr          ; DI = куда копировать (приёмник)
       mov    si,oldStr+2        ; SI = начало строки (источник)
       add    si,cx              ; смещаемся в конец

;- Ищем адрес и длину очередного слова (справа/налево) ----------
@find: std                     ; флаг DF=1 (обратный шаг)
       sub    bx,bx            ; BX = 0 (будет длиной слова)
@01:   lodsb                   ; AL = очередной байт из SI (SI-1)
       cmp    al,' '           ; сравнить с пробелом
       je     @stop            ; если истина..
       inc    bx               ; иначе: считаем длину слова
       dec    cx
       jnz    @01              ; промотать, пока СХ > 0

;- Встретили пробел. Копируем слово в вых.буфер -----------------
@stop: cld                     ; флаг DF=0 (прямой шаг)
       push   cx si            ; запомнить текущую позицию в строке
       add    si,2             ; коррекция указателя на начало слова
       mov    cx,bx            ; СХ = длина слова
       rep    movsb            ; копируем из SI в DI !!!
       mov    byte[di],' '     ; вставить пробел-разделитель
       inc    di               ; сдвинуть указатель в приёмнике
       pop    si cx            ; восстановить текущую позицию.
       or     cx,cx            ; проверить CX на нуль
       jnz    @find            ; повторить, если не равно

;- Выводим результат на экран -------
       mov    ah,9             ;
       mov    dx,mes1          ; мессага
       int    21h              ;
       mov    dx,newStr        ; изменённая строка
       int    21h              ;

exit:  xor   ax,ax             ;
       int   16h               ; ждать клаву..
       int   20h               ; на выход!
Нашедшего выход - затаптывают первым..
R71MT вне форума Ответить с цитированием
Старый 07.12.2019, 14:00   #5
R71MT
Участник клуба
 
Аватар для R71MT
 
Регистрация: 16.06.2011
Сообщений: 1,375
По умолчанию

Цитата:
Сообщение от Solo_ Посмотреть сообщение
Должен быть организован ввод(и вывод) через прерывание, именно в командной строке, а не в самом коде,
Если ввод в ком.строке, тогда запускаешь прогу с параметром в виде строки. Введённую строку потом найдёшь по смещению 0х80 в PSP (от начала выделенного тебе сегмента).
Нашедшего выход - затаптывают первым..
R71MT вне форума Ответить с цитированием
Старый 07.12.2019, 14:13   #6
R71MT
Участник клуба
 
Аватар для R71MT
 
Регистрация: 16.06.2011
Сообщений: 1,375
По умолчанию

вот так выглядит запуск программы с аргументом "Hello World! 123456" в ком.строке. Соответственно SI настраиваешь на 0х80, а дальше всё так-же (первый байт 0х12 - это длина аргумента):
Изображения
Тип файла: png avp.png (17.4 Кб, 7 просмотров)
Нашедшего выход - затаптывают первым..
R71MT вне форума Ответить с цитированием
Ответ

Здесь нужно купить рекламу за 20 тыс руб в месяц! ) пишите сюда - alarforum@yandex.ru
Без учёта ботов - 20000 человек в день, 350000 в месяц.

Опции темы


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Определите меня с выбором пути обучения Raxxxy Помощь студентам 8 17.01.2012 18:54
Не могу найти книгу Стивена Праты "Язык программирования C. Лекции и упражнения". Может есть у кого? Catharsis Общие вопросы C/C++ 0 10.06.2010 12:46
У кого есть идеи по созданию мордоленты? slips JavaScript, Ajax 1 29.10.2009 21:21
Как решать японские кроссворды или судоку? Может у кого-нибудь есть идеи? TwiX Свободное общение 2 16.08.2009 07:56