Обмен в исходном файле соседних слов местами - 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 и предназначен для обмена соседних слов в исходной строке. Процесс обмена осуществляется путем вращения подстрок вправо и влево, а затем восстановления разделителя после слова. Однако, чтобы точно понять, как работает код, необходимо более подробное описание и контекст задачи. Кроме того, для полноценной работы кода может потребоваться дополнительная информация, такая как размер строки, указатель на строку, указатель на разделитель и т.д.

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

5   голосов , оценка 4.8 из 5
Похожие ответы