Обмен в исходном файле соседних слов местами - Assembler/emu8086
Формулировка задачи:
Всех приветствую!
Прошу помочь в написании программы на Ассемблере,которая меняет ближние слова местами
Задание: Программа выполняет такую функцию, как обработка прочитанных данных, обмен в исходном файле соседних слов местами (1-2, 3-4, 5-6 и т.д).
Пример:
ДО: «Мама мыла раму дома»
ПОСЛЕ: «Мыла мама дома раму». Обработанный результат записывается в новый текстовый файл, созданный во время работы.
Заранее,огромное спасибо!
Решение задачи: «Обмен в исходном файле соседних слов местами»
textual
Листинг программы
.model small .stack 100h .data DelimChar db ' ' ;символ, разделитель слов CrLf db 0Dh, 0Ah, '$' msgPressAnyKey db 'Press any key to exit...', '$' ;характеристики нечётного по порядку слова ptrOddWord dw ? ;адрес нечётного по порядку слова LenOddWord dw ? ;длина нечётного по порядку слова ;переменные для файлового обмена InFileName db 'InFile.txt', 0 InFileHandler dw ? OutFileName db 'OutFile.txt', 0 OutFileHandler dw ? errFileOpen db 'File open error', '$' errFileRead db 'File read error', '$' errFileClose db 'File close error', '$' String db 512 dup(?) StrLen dw $-String .code main proc mov ax, @data mov ds, ax ;ввод исходной строки из файла ; - открытие файлов mov ah, 3Dh mov al, 00h ;открыть для чтения lea dx, [InFileName] int 21h jnc @@InFileOpenOk mov ah, 09h lea dx, [errFileOpen] int 21h jmp @@Exit @@InFileOpenOk: mov [InFileHandler], ax ; - читать из файла mov ah, 3Fh mov bx, [InFileHandler] lea dx, [String] mov cx, 512 int 21h jnc @@InFileReadOk mov ah, 09h lea dx, [errFileRead] int 21h jmp @@Exit @@InFileReadOk: mov [StrLen], ax ; - закрытие файла mov ah, 3Eh mov bx, [InFileHandler] int 21h jnc @@InFileCloseOk mov ah, 09h lea dx, [errFileClose] int 21h @@InFileCloseOk: ;вывод исходной строки на экран mov ah, 40h mov bx, 1 mov cx, [StrLen] lea dx, [String] int 21h mov ah, 09h lea dx, [CrLf] int 21h ;подготовка к выполнению строковых цепочечных команд cld mov ax, ds mov es, ax lea si, [String] mov cx, [StrLen] mov dx, 0 ;порядковый номер найденного слова jcxz @@Break @@ForEachWord: push cx ;выделяем слово call GetNextWord jcxz @@Break ;прервать поиск при отсутствии новых слов inc dx test dx, 1 jz @@ReplaceWords ;если порядковый номер слова нечётный, ;то сохранить его индекс и длину mov [ptrOddWord], si mov [LenOddWord], bx jmp @@NextWord ;если порядковый номер слова чётный ;обменять его с предыдущим словом (с нечётным ;порядковым номером) @@ReplaceWords: push si push cx ;вращение подстроки влево mov cx, si ;длина подстроки add cx, bx sub cx, [ptrOddWord] mov ax, si ;величина сдвига sub ax, [ptrOddWord] mov si, [ptrOddWord] call ArrRotateLeft ;вращение подстроки вправо - восстановление разделителя sub cx, bx add si, bx call ArrRotateRight ;восстановление контекста поиска pop cx pop si @@NextWord: ;переход к разделителю после слова add si, bx sub cx, bx jnz @@ForEachWord @@Break: ;вывод результатов ; - на экран mov ah, 40h mov bx, 1 mov cx, [StrLen] lea dx, [String] int 21h mov ah, 09h lea dx, [CrLf] int 21h ; - в файл ; - открытие файла mov ah, 3Ch lea dx, [OutFileName] mov cx, 0 int 21h jnc @@OutFileOpenOk mov ah, 09h lea dx, [errFileOpen] int 21h jmp @@Exit @@OutFileOpenOk: mov [OutFileHandler], ax ; - записать в файл mov ah, 40h mov bx, [OutFileHandler] lea dx, [String] mov cx, [StrLen] int 21h jnc @@OutFileReadOk mov ah, 09h lea dx, [errFileRead] int 21h jmp @@Exit @@OutFileReadOk: mov [StrLen], ax ; - закрытие файла mov ah, 3Eh mov bx, [OutFileHandler] int 21h jnc @@OutFileCloseOk mov ah, 09h lea dx, [errFileClose] int 21h @@OutFileCloseOk: @@Exit: mov ax, 4C00h int 21h main endp ;перейти к следующему слову в строке ;на входе: ; ds:si - адрес строки ; cx - длина строки ;на выходе: ; ds:si - адрес первого символа слова в строке ; cx - длина строки от первого символа нового слова ; bx - длина найденного слова GetNextWord proc push ax ;push bx ;push cx push dx ;push si push di push es xor bx, bx jcxz @@gnwExit mov al, [DelimChar] ;пропуск разделителей (пробелов) @@SkipDelimiters: cmp al, [si] jne @@NewWord inc si loop @@SkipDelimiters jcxz @@gnwExit ;если строка закончилась - выйти ;найдено новое слово @@NewWord: ;пропускаем все буквы слова до разделителя ;вычисляем длину слова push cx mov di, si xor bx, bx ;bx - длина очередного слова @@WhileWord: cmp al, [di] je @@gnwBreak inc bx ;увеличиваем длину слова inc di ;переходим к следующему символу loop @@WhileWord @@gnwBreak: pop cx @@gnwExit: push ds pop es pop es pop di ;pop si pop dx ;pop cx ;pop bx pop ax ret GetNextWord endp ;вращение массива байт влево ;на входе: ; ds:si - адрес (указатель) на массив ; cx - длина массива ; ax - величина сдвига ;Reversal algorithm for array rotation ;Function to left rotate arr[] of size n by d ; reverse(arr[], 0, d-1) ; reverse(arr[], d, n-1) ; reverse(arr[], 0, n-1) ArrRotateLeft proc push ax push cx push dx push si push di or ax, ax jz @@arlExit mov dx, si ; reverse(arr[], 0, d-1) mov si, dx mov di, si add di, ax dec di call ArrReverse ; reverse(arr[], d, n-1) mov si, dx mov di, dx add si, ax add di, cx dec di call ArrReverse ; reverse(arr[], 0, n-1) mov si, dx mov di, dx add di, cx dec di call ArrReverse @@arlExit: pop di pop si pop dx pop cx pop ax ret ArrRotateLeft endp ;реверс элементов массива ;на входе: ; ds:si - адрес (указатель) на первый элемент массива ; ds:di - адрес (указатель) на последний элемент массива ArrReverse proc push ax @@reverse: mov al, [si] mov ah, [di] mov [si], ah mov [di], al inc si dec di cmp si, di jb @@reverse pop ax ret ArrReverse endp ;вращение массива байт вправо на 1 элемент ;на входе: ; ds:si - адрес (указатель) на массив ; cx - длина массива ArrRotateRight proc push ax push bx push cx push dx push si push di or ax, ax jz @@arrExit cmp cx, 1 jbe @@arrExit dec cx mov bx, si mov di, si add di, cx mov al, [di] mov si, di dec si std rep movsb mov [bx], al cld @@arrExit: pop di pop si pop dx pop cx pop bx pop ax ret ArrRotateRight endp end main
Объяснение кода листинга программы
Исходя из представленного кода, можно сделать вывод, что он написан на языке Assembler и предназначен для обмена соседних слов в исходной строке. Процесс обмена осуществляется путем вращения подстрок вправо и влево, а затем восстановления разделителя после слова. Однако, чтобы точно понять, как работает код, необходимо более подробное описание и контекст задачи. Кроме того, для полноценной работы кода может потребоваться дополнительная информация, такая как размер строки, указатель на строку, указатель на разделитель и т.д.
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д