Skip to content

Лабораторная работа №6 по fasm

License

Notifications You must be signed in to change notification settings

IUTen/YPS_ASM_LR6

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 

Repository files navigation

Static Badge

Условия задачи

Переделать программу, которая выводит на экран содержимое памяти по 16 байт в одной строке. Вывод программы сохранить в файл с именем "ФИО.txt" в текущей директории.

Пример:

10 11 12 13 14 15 16 17 18 19 1А 1В 1С 1D 1E 1F

20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F

Общая идея решения

В кратце, идея решения. Сначала создаётся и открывается файл, с нужным названием. Далее программа пробегает по внешнему и вложенному циклу, формируя таблицу. На каждой итерации вложенного цикла мы записываем в регистры AH и AL ASCII коды символов, прочитанных из памяти. Их мы записываем в буффер и с его помощью записываем в файл информацию.

Разбор кода

Объявления

format MZ
entry code_segment:main
stack 400h
;---------------------------
segment data_seg

file_name db "SamsonovEM.txt$"

buff db 2 dup(?) 

Здесь стоит обратить внимание на две вещи. Первое, название файла с дампом задаётся через определение байта. Второе, буффер на 2 байта, в который будет записываться байт для дампа.

Основной блок кода

segment code_segment

main:
    mov ax, data_seg                        ;Записываем в DS сегмент с данными
    mov ds, ax
    mov dx, file_name

    call create_and_open_file               ;Создаём и открываем файл
    mov bx, ax                              ;Кладём логический номер файла в BX. Нужно для вывода
    
    mov ax, data_seg                        ;Записываем в DS сегмент с данными
    mov ds, ax

    mov ax, 0xb800                          ;Записываем сегмент для вывода дампа
    mov es, ax
    mov di, 512                             ;Записываем смещение для вывода дампа

    mov cx, 16                              ;Цикл вывода дампа в файл
    row_run:
        push cx
        mov cx, 16
        column_run:
            call get_ahal_byte
            call write_block_dump
            call write_space
            loop column_run
        call write_endl
        pop cx
        loop row_run
    
    jmp end_running

Рассмотрим подробнее. Первые три строки блока main это подготовка к работе с сегментом данных (в программе .com взаимодействие происходит иначе). Далее идёт вызов функции create_and_open_file, она создаёт и открывает файл, а также записывает в AX логический номер файла, чтобы в последствии можно было в него записать данные. Поскольку регистр AX часто используется, сохраним номер файла в BX.

mov ax, 0xb800                          ;Записываем сегмент для вывода дампа
mov es, ax
mov di, 512                             ;Записываем смещение для вывода дампа

Здесь мы задаём сегмент и смещение памяти, дамп которой мы будем записывать в файл.



mov cx, 16                              ;Цикл вывода дампа в файл
    row_run:
        push cx
        mov cx, 16
        column_run:
            call get_ahal_byte
            call write_block_dump
            call write_space
            loop column_run
        call write_endl
        pop cx
        loop row_run

Это основной цикл работы программы. Здесь мы пробегаем по строкам и столбцам. Для каждой ячейки таблицы мы читаем из памяти данные и записываем их в файл с помощью функций, которые мы рассмотрим далее.

Блок чтения данных из памяти

Функция читает данные по адресу ES:DI и запиывает символы ASCII в AH и AL. Также увеличивает DI на 1, чтобы потом продолжить чтение следующего участка памяти.

;Записывает в AX байт из ES:DI, увеличивает DI на 1.
;В AH код первого символа в AL код второго
get_ahal_byte:
    push bx

    xor ax, ax                              ;0 в АХ                             
    mov al, byte[es:di]                     ;Прочитали память в AX
    push ax                                 ;Сохранили данные на вывод в стек

    shr al, 4                               ;Смещаем значение вправо, чтобы оставить один символ
    and al, 0xf                             ;Через маску обнуляем всё остальное                    
    cmp al, 0x9                             ;Проверяем цифра это или буква
    ja symb_ah
    ;---Блок с цифрой---                    ;Запись ASCII кода цифры
        add al, 0x30
        mov ah, al
        jmp part_two
    ;-------------------

    symb_ah:                                ;Запись ASCII кода буквы
        add al, 0x37
        mov ah, al

    part_two:
    mov bh, ah                              ;Сохраняем найденный код в BH
    pop ax

    and al, 0xf                             ;Оставляем крайний символ
    cmp al, 0x9                             ;Проверяем цифра это или буква
    ja symb_al
    ;---Блок с цифрой---                    ;Запись ASCII кода цифры
        add al, 0x30
        jmp part_three
    ;-------------------

    symb_al:                                ;Запись ASCII кода символа
        add al, 0x37

    part_three:                             ;Настройка значений
    add di, 1
    mov ah, bh
    pop bx
    ret

Комментарии есть в самом коде, так что пробежимся в целом по концепции. В начале обнуляем регистр AX, чтобы предотвратить какие-либо ошибки при чтении и читаем нужный нам участок памяти в регистр AL. Дальше мы делаем сдвиг вправо, чтобы нужная нам часть осталась с краю. С помощью маски и инструкции AND мы точно оставляем нужную нам часть, а после определяем ASCII код символа. Проделываем то же самое со вторым символом, только там уже не понадобится сдвиг, так как мы изначально читаем крайний символ. В конце мы уточняем значения регистров и возвращаемся из функции.

Блоки записи в файл

;В AH и AL должны лежать два символа на вывод
write_block_dump:                           ;В BX должен лежать логический номер файла, в СХ кол-во байт на запись - для записи в файл
    pusha
    
    push ax                                 ;Запомнили значение
    mov byte[ds:buff], ah                   ;Записываем в буфер значение на вывод в файл
    pop ax                                  ;Восстановили значение
    mov byte[ds:buff+1], al                 ;Записываем в буфер значение на вывод в файл
    mov cx, 2                               ;Указываем, что выведем 1 символ
    mov dx, buff                            ;Для работы функции прерывания, указываем смещение. Строка вывода: DS:DX
    mov ah, 0x40                            ;Функция записи в файл
    int 0x21                                ;Вызываем прерывание

    popa
    ret

write_space:                                ;Блок по выводу пробела в файл
    pusha

    mov byte[ds:buff], " "              
    mov cx, 1
    mov dx, buff
    mov ah, 0x40
    int 0x21

    popa
    ret

 write_endl:                                ;Блок по выводу конца строки в файл
    pusha

    mov byte[ds:buff], 0xA
    mov cx, 1
    mov dx, buff
    mov ah, 0x40
    int 0x21

    popa
    ret   

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

  1. Записали по адресу DS:DX данные, которые необходимо записать
  2. В BX должен лежать логический номер файла. Он кладётся в AX при создании файла
  3. В CX указываем кол-во вывода. Если положить туда 2, то данные из DS:DX запишутся в файл дважды
  4. В AH кладём 0х40 - функция записи в файл прерывания 0х21
  5. Собственно вызываем прерывание 0x21

Блок с созданием файла

create_and_open_file:                       ;В ds:dx имя файла. В AX запишется логический номер файла
    push cx

    xor cx,cx                               ;Обнуляем СХ, чтобы создался обычный файл(без флагов) 
    mov ah, 0x3C                            ;Функция создания файла
    int 0x21                                ;Вызываем прерывание

    pop cx
    
    ret

Для создания обычного файла мы должны сделать следующее:

  1. В память DS:DX нужно записать название создаваемого файла.
  2. В CX должен лежать 0 для создания обычного файла.
  3. Вызвать прерывание 0x21 с функцией 0x3C.

Послесловие

Если вы захотите что-то спросить, узнать, дополнить, уточнить, смело открывайте issue.

About

Лабораторная работа №6 по fasm

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published