2. Этапы создания программы на языке Ассемблер. Вывод строки на экран

5. Исполняемые файлы. Консольный ввод/вывод символа

Цель работы: ознакомление с типами исполняемых файлов, приобретение навыков использования функций ввода/отображения символа.

Теоретическая часть

Исполняемые файлы

Рассмотрим форматы исполняемых файлов типа .comи .exe.

В файлах типа .comпрограмма состоит из одного сегмента. Код и данные могут занимать до 64Kb и располагаться в одном сегменте. Для создания .com–файлов используется модель памяти tiny. Чтобы получить .com–файл на этапе линкования, необходимо задать параметр /t.

Исходный код программы начинается с псевдокоманды ORG 100h для сохранения пространства памяти размером 100h под заголовок файла. Данные могут быть размещены в любом месте программы, но рекомендуется  объявлять их вначале.

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

Регистр DS , как и регистр CS, содержит адрес сегмента кода. Это делается компилятором автоматически.

Точка входа в программу не описывается. Программа всегда начинается с адреса 100h. Завершить программу можно либо с помощью команды RET (возврат из подпрограммы), либо вызовом функции 4ch прерывания 21h.

Образец программы типа .com:

.model tiny
.code
	org 100h 		
start:
	jmp label
...			; область объявления данных
label:
...			;текст программы
	mov ah,4ch
	int 21h		; выход из программы
end start

Для получения файла с расширением .com необходимо выполнить следующие команды (предполагается, что имя исходного файла p.asm):

tasm p.asm

tlink /t p.obj

Формат .exe– самый распространенный для исполняемых файлов. В программах этого формата может быть несколько сегментов. Этот формат используется для программ с большим объемом кода. Размер программы ограничивается только размером доступной памяти.

Программист должен сам следить за правильностью адресов, хранящихся в сегментных регистрах, и явно их инициализировать. Для программ типа .exe можно использовать любую модель памяти: tiny, small, compact, medium, large, huge. Пример программы в формате .exe рассмотрен в предыдущих работах.

Ввод/вывод символа функциями 01h и 02h прерывания 21h

Вызов функции01hпрерывания 21h для введения символа с клавиатуры выполняется следующим образом:

mov   ah, 01h     ;номер вызываемой функции записывается в регистр ah

int       21h             ;вызов прерывания.

;код введенного символа помещается в регистр al

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

Вывод символа на экран можно выполнить с помощью функции02h прерывания 21h:

mov ah, 02h            ;определяем номер функции

mov dl, <код>        ;код символа помещается в регистр dl

int      21h                    ;вызов прерывания

Рассмотрим пример программы, в которой символ вводится с клавиатуры. Введенный символ сохраняется в переменной S, а затем выводится на консоль. Программа будет иметь тип .com:

.model tiny
.code
org 100h
start: jmp 	label_start
s		db 	? 	;объявление неинициализированной переменной
mes1 	db 	‘Введите символ: $’
mes2	db 	‘Вы ввели символ:,10,13,$’
 
label_start:
; вывод первого сообщения
mov	ah,9
lea 	dx,mes1
int 	21h
; ввод символа 
mov 	ah, 1
int 	21h		;в al находится код введенного символа
mov 	s,al		;сохраним его в s
; вывод сообщения 2 
mov 	ah,9
lea 	dx,mes2
int 	21h
; вывод на экран введенного символа
mov 	ah, 2
mov 	dl, s	;ранее мы сохранили символ в переменной s
int 	21h
; завершение программы
mov 	ah, 4ch
int 	21h
end	start
end

Задания

  1. Написать программу для форматов .com и .exe.
  2. Сравнить размеры полученных файлов. Объяснить, почему файлы этих форматов различаются в размерах.

Варианты задач

1. Массив символов s1 определен в сегменте данных. С клавиатуры вводятся строка s2 и символы a1 и a2. Написать программу, которая выводит на экран входные данные по следующему сценарию:
Введите строку s2:
s2
Введите символ a1:
a1
Введите символ a2:
a2
Результат: s1ba1ba2bs2 (b – символ пробела)

2. Массивы символов s1 и s2 определены в сегменте данных. С клавиатуры вводятся символы a1 и a2 и строка s3. Написать программу, которая выводит на экран входные данные по следующему сценарию:
Введите строку s3:
s3
Введите символ a1: a1
Введите символ a2:
a2
Результат: a1bbs2a2bbs1bbs3 (b – символ пробела)

3. Массив символов s1 определен в сегменте данных. С клавиатуры вводятся строки s2 и s3 и символ a1. Написать программу, которая выводит на экран входные данные по следующему сценарию:
Введите строку s2:
s2
Введите символ a1:
a1
Введите строку s3: s3
Результат: s1bba1s1a1bbs2s3 (b – символ пробела)

4. Массив символов s1 определен в сегменте данных. С клавиатуры вводятся строка s2 и символы a1 и a2. Написать программу, которая выводит на экран входные данные по следующему сценарию:
Введите строку s2: s2
Введите символ a1:
a1
Введите символ a2: a2
Результат: a1bbs1bba2bbs1bbs2 (b – символ пробела)

5. Массив символов s1 определен в сегменте данных. С клавиатуры вводятся строки s2 и s3 и символы a1, a2 и a3. Написать программу, которая выводит на экран входные данные по следующему сценарию:
Введите строку s2: s2
Введите символ a1: a1
Введите символ a2:
a2
Введите символ a3: a3
Введите строку s3:
s3
Результат: s1a1bba3a2a2bbs2bbs3 (b – символ пробела)

6. Массивы символов s1 и s2 определены в сегменте данных. С клавиатуры вводятся строка s3 и символ a1. Написать программу, которая выводит на экран входные данные по следующему сценарию:
Введите строку s3:
s3
Введите символ a1: a1
Результат: a1bbs2a1s1bbs3bba1 (b – символ пробела)

7. Массив символов s1 определен в сегменте данных. С клавиатуры вводятся строка s2 и символ a1. Написать программу, которая выводит на экран входные данные по следующему сценарию:
Введите символ a1:
a1
Введите строку s2:
s2
Результат: s1bba1s1bbs2bba1 (b – символ пробела)

8. Массив символов s1 определен в сегменте данных. С клавиатуры вводятся строка s2 и символы a1 и a2. Написать программу, которая выводит на экран входные данные по следующему сценарию:
Введите символ a1:
a1
Введите символ a2: a2
Введите строку s2: s2
Результат: a2s1bbs1a1bbs2 (b – символ пробела)

9. Массивы символов s1 и s2 определены в сегменте данных. С клавиатуры вводятся строка s3 и символы a1 и a2. Написать программу, которая выводит на экран входные данные по следующему сценарию:
Введите символ a1: a1
Введите символ a2: a2
Введите строку s3:
s3
Результат: s1a1bba2bbs2bbs3 (b – символ пробела)

10. Массивы символов s1 и s2 определены в сегменте данных. С клавиатуры вводятся строка s3 и символы a1 и a2. Написать программу, которая выводит на экран входные данные по следующему сценарию:
Введите символ a1: a1
Введите строку s3:
s3
Введите символ a2:
a2
Результат: a1bbs2a2s1bbs3 (b – символ пробела)

11. Массивы символов s1 и s2 определены в сегменте данных. С клавиатуры вводятся строка s3 и символ a1. Написать программу, которая выводит на экран входные данные по следующему сценарию:
Введите строку s3: s3
Введите символ a1:
a1
Результат: a1bs2a1s1bbba1bs3 (b – символ пробела)

12. Массивы символов s1 и s2 определены в сегменте данных. С клавиатуры вводятся строка s3 и символы a1 и a2. Написать программу, которая выводит на экран входные данные по следующему сценарию:
Введите строку s3:
s3
Введите символ a1: a1
Введите символ a2: a2
Результат: s2bba2s1bs3ba1s3 (b – символ пробела)

13. Массивы символов s1 и s2 определены в сегменте данных. С клавиатуры вводятся строка s3 и символ a1. Написать программу, которая выводит на экран входные данные по следующему сценарию:
Введите символ a1: a1
Введите строку s3: s3
Результат: s2ba1bs1bs3ba1bs1 (b – символ пробела)

14. Массивы символов s1 и s2 определены в сегменте данных. С клавиатуры вводятся строка s3 и символы a1 и a2. Написать программу, которая выводит на экран входные данные по следующему сценарию:
Введите символ a1: a1
Введите символ a2:
a2
Введите строку s3: s3
Результат: s1ba2ba1bs2bs3ba1 (b – символ пробела)

15. Массивы символов s1 и s2 определены в сегменте данных. С клавиатуры вводятся строка s3 и символ a1. Написать программу, которая выводит на экран входные данные по следующему сценарию:
Введите строку s3: s3
Введите символ a1: a1
Результат: a1bs2ba1s1bs3ba1ba1 (b – символ пробела)

16. Массивы символов s1 и s2 определены в сегменте данных. С клавиатуры вводятся строка s3 и символы a1 и a2. Написать программу, которая выводит на экран входные данные по следующему сценарию:
Введите символ a1: a1
Введите строку s3:
s3
Введите символ a2: a2
Результат: a1bs2a1s3bbs1ba2 (b – символ пробела)

Лаб4. Команды пересылки. Ввод/вывод строки функциями 3Fh и 40h прерывания 21h.

Цель работы: ознакомление с возможностями буферизированного ввода/вывода, различными командами пересылки данных и закрепление навыков выполнения и отладки программ на ЭВМ с использованием интерактивных отладчиков.

Теоретическая часть

Команды пересылки данных

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

Команды пересылки данных делятся на следующие группы:

  • команды общего назначения;
  • команды пересылки адреса;
  • команды пересылки флажков.

Рассмотрим некоторые из них.

Команды общего назначения

Команда MOV

Это основная команда общего назначения. Она позволяет переслать:

  • байт или слово между регистрами или между регистром и ячейкой памяти;
  • непосредственно адресуемое значение в регистр или ячейку памяти.

Формат команды:

MOV <приемник>, <источник>

Примеры:

mov AX, TABLE     ;переслать из памяти с адресом TABLE в регистр AX

mov TABLE, AX     ;переслать из регистра AX в память с адресом TABLE

mov CL, 25                ;переслать в регистр СLчисло 25

mov CX, BX              ;переслать в регистр CX содержимое BX

Запрещается:

  • непосредственно пересылать данные из одной ячейки памяти в другую. Для этого надо использовать промежуточный регистр;
  • загружать непосредственно адресуемый операнд напрямую в регистр сегмента. Для этого используют промежуточный регистр общего назначения;
  • непосредственно пересылать значение одного сегментного регистра в другой сегментный регистр;
  • использовать сегментный регистр CS в качестве приемника.

Команда пересылки адреса LEA

LEA – команда загрузки исполнительного адреса, пересылающая относительный адрес (смещение) ячейки памяти в 16–битовый регистр общего назначения, регистр указателя или индексный регистр.

Формат команды:

LEA <регистр>, <память>

Пример: lea BX, TABLE[DI]  ;если регистр DI содержит 5, то в

;регистре BX будет смещение ячейки

;TABLE+5 в сегменте, адресуемом

;текущим значением регистра DS

Команды PUSHиPOP

Команда PUSH помещает содержимое регистра или ячейки памяти размером в слово в вершину стека. Формат команды:

PUSH <источник>

Примеры:

push SI

push CS

push TABLE[BX][DI]

Команда POP извлекает слово с вершины стека и помещает его в ячейку памяти или регистр. Формат команды:

POP <приемник>

Пример: POP AX

Под вершиной стека понимается ячейка памяти в сегменте стека, смещение которой содержится в указателе SPSP всегда указывает на слово, помещенное в стек последним. Команда PUSH уменьшает значение SP на 2, а команда POP – увеличивает на 2.

Команды пересылки флажков PUSHF и POPF

Команда PUSHF помещает содержимое регистра флажков в вершину стека. Формат команды:

PUSHF

Команда POPF извлекает слово с вершины стека и помещает его в регистр флагов. Формат команды:

POPF

Ввод/вывод строки функциями 3Fh и 40h

При вводе строки с помощью функции 3Fh необходимо описать буфер для вводимых символов. Надо только помнить, что, в отличие от функции 0Ah, функция 3Fh сохраняет в конце введенной строки не один, а два символа:0Ah – код новой строки и 0Dh – код клавиши Enter, поэтому буфер должен быть на два байта вместительней.

Кроме того, при вводе с помощью этой функции процессор не выдает звукового сигнала при заполнении буфера и клавиатура не блокируется. Все вводимые символы сначала попадают в системный буфер ввода-вывода, а затем процессор перемещает нужное число символов в заданную в программе область памяти. Лишние символы остаются в системном буфере.

Они будут считаны из него при повторном вызове функции ввода, что может привести к неверному функционированию программы, поэтому пользователь должен сам отслеживать количество введенных символов.

Например, если буфер для ввода объявлен как

Stroka  DB   12 DUP(?) ,

то вызов функции 3Fhвыглядит следующим образом:

mov AH, 3Fh               ;номер функции помещаем в регистр AH

lea DX, Stroka         ;адрес буфера ввода – в регистр DX.

;эту строчку кода можно

;заменить на MOV DX, OFFSET Stroka

mov BX, 0                 ;в BX хранится дескриптор стандартного входного потока

mov CX, 12               ;в CX – количество вводимых символов

int21h                           ;вызов прерывания

После выполнения этой функции в регистре AL хранится количество введенных символов с учетом двух дополнительных символов, в регистр AH помещается возможный код ошибки.

Функция 40h выводит строку на экран. Вызов функции осуществляется следующим образом:

mov  AH, 40h              ;номер функции помещаем в регистр AH

lea  DX, Stroka        ;адрес буфера вывода – в регистр DX.

mov  BX, 1                    ;в BX хранится дескриптор стандартного

;выходного потока

mov  CX, 10                ;в CX – количество выводимых символов

int  21h                      ;вызов прерывания

Выходной параметр – регистр AL содержит количество выведенных символов.

Задания

  1. Написать программу, соответствующую вашему варианту из третьей лабораторной работы, с использованием функций 3Fh и 40h для ввода и вывода строк на экран. Символы копировать через стек с помощью команд PUSH и POP.
  2. Выполнить программу под управлением отладчика TD. Провести пошаговую трассировку программы, отслеживая на каждом шаге содержимое сегмента данных. Изучить изменение указателя стека SP, указателя команд IP и сегмента данных от шага к шагу выполнения программы.

 

Работа с отладчиком Turbo Debugger (TD)

Приложение B. Работа с отладчиком Turbo Debugger (TD)

Для запуска программы под управлением отладчика необходимо с клавиатуры ввести команду TD prog.exe. На экране появится окно отладчика:tdebugger

Горячие клавиши отладчика:

Alt+F2                   – Установка точки останова.

F2                          – Снятие точки останова.

Alt + F3                 – Закрыть окно.

F4                          – Выполнить программу до заданной точки.

Alt + F4                 – Back Trace.

F5                          – ZOOM окна.

Alt + F5                 – Просмотр окна выполнения программы.

F7                          – Trace Into, шаг отладки с углублением в подпрограммы.

F8                          – Step Over, полный шаг отладки без углубления в подпрограммы.

F9                          – Run, запуск тестируемой программы на выполнение;
.                                запуск после точки останова.

Ctrl + NumLock   – Прервать выполнение тестируемой программы,
.                                   запущенной по команде RUN.

F10                        – Главное меню.

Tab, Shift + Tab   – Переход к следующему/предыдущему окну.

A..Z                        – Ввод команд Ассемблера в тело тестируемой

.                                  программы по адресу в позиции курсора.

Ctrl + G                 – Задать начальный адрес интересуемой области памяти

Ctrl+C                   – Изменение данных в регистре или ячейке памяти

Ctrl+D                   – При редактировании ячейки памяти можно установить
.                                 тип: byte, word и т.д.

Ctrl+S                   – Поиск необходимой инструкции или содержимого
.                                 ячейки памяти

Alt + X                  – Выход из отладчика в DOS.

Комментарии к рисунку:

Все числа в команде представлены в шестнадцатеричном виде. Все метки и переменные представлены своими смещениями

Картина окна кода состоит из трех столбцов:

  1. Адрес. Смещения команд относительно начала сегмента.
  2. Машинный код команд.
  3. Исходный текст программы на языке Ассемблера.

Картина содержимого памяти (зона данных) состоит из двух частей:

  1. Шестнадцатеричная часть. Каждый байт выводится в виде шестнадцатеричного числа.
  2. Часть ASCII. Байты выводятся в виде символов ASCII.
  3. При размещении данных в памяти младшие байты располагаются по младшим адресам, а старшие по старшим. Отладчик показывает память от младших адресов к старшим, поэтому данные, определенные, например, как

dw  1234h, 5678h, dd  9ABCDEF1h

dt 10201234567890ABCDEFh

пользователь увидит, как это показано на нижеследующей схеме.

Mem1Размещение данных в памяти

3. Способы адресации памяти. Ввод и вывод строки функциями 09h и 0Аh прерывания 21h.

3. Способы адресации памяти. Ввод и вывод строки функциями 09h и 0Аh прерывания 21h

Цель работы:  приобретение навыков в составлении простых программ, содержащих ввод данных и вывод результатов; получение знаний о режимах адресации микропроцессора i8088, о выполнении и отладке программ на ЭВМ.

Теоретическая часть

Режимы адресации микропроцессора i8088

Микропроцессор (МП) i8088 может использовать различные режимы адресации для получения доступа к данным, которыми должна оперировать программа. Ассемблер определяет режим на основе формата операнда в исходной программе.

Можно выделить семь различных режимов адресации: регистровая, непосредственная, прямая, косвенная регистровая, по базе, прямая с индексированием, по базе с индексированием.

Простейшими режимами адресации являются регистровая и непосредственная, поскольку в этом случае МП получает значение операнда из регистра или непосредственно из команды. При остальных пяти режимах МП должен вычислить адрес ячейки памяти, затем прочитать из нее значение операнда.

При регистровой адресации МП извлекает операнд из регистра или загружает его в регистр. Например,

mov ax, cx          ; пересылка содержимого регистра cx в регистр ax

Непосредственная адресация позволяет указать  значение константы в качестве второго операнда команды. Например,

mov cx, 500        ; загрузить в регистр cx значение 500

Для описания других режимов адресации введем понятие исполнительного адреса.

Исполнительным адресом называется смещение операнда относительно начала сегмента, в котором он находится. Все имена (переменные, метки), используемые в программе по-другому называются символическими адресами и являются смещениями относительно начала сегмента, в котором они находятся и представляют собой целое число.

При прямой адресации исполнительный адрес является составной частью команды. МП добавляет этот адрес к сдвинутому на 4 бита (т.е. умноженому на 16) содержимому регистра сегмента данных DS и получает 20–битовый физический адрес операнда. Обычно прямая адресация применяется, если операндом служит метка (символический адрес). Например,

mov ax, table ;загрузка в регистр ax содержимого
;ячейки памяти (2 байта) с меткой table

При косвенной регистровой адресации исполнительный адрес операнда содержится в базовом регистре bx, регистре указателя базы bp или в индексном регистре si или di. Регистровые операнды косвенной адресации необходимо заключать в квадратные скобки. Например,

mov ax, [bx] ;загрузить в регистр ax содержимое ячейки,
;исполнительный адрес, которой находится в
;регистре bx

Чтобы поместить смещение (относительный адрес) ячейки table в регистр bx, можно использовать директиву OFFSET. Например,

mov bx, offset table ;поместить в регистр bx смещение
;ячейки table
;регистре bx

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

При адресации по базе исполнительный адрес вычисляется сложением содержимого регистра bx или bp и сдвига, измеряемого в байтах. Например, следующие команды выполняют одно и то же действие:

mov ax, [bx]+4    ;загрузить в регистр ax содержимое по адресу,
mov ax, [bx+4]    ;отстоящему на 4 байта от ячейки, исполнительный
mov ax, 4[bx]      ;адрес которой находится в регистре bx

При прямой адресации с индексированием исполнительный адрес вычисляется как сумма значений сдвига и индексного регистра si или di. Этот тип адресации удобен для доступа к элементам таблицы, когда сдвиг указывает на начало таблицы, а индексный регистр – на ее элемент. Например,

mov di, 2
mov al, table[di]
;загрузить в al третий элемент
; (со смещением 2) таблицы table

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

mov ax, [bx+2+di]
mov ax, [bx+2][di]
mov ax, [bx][di+2]

При всех способах адресации (кроме тех, где используется регистр bp) исполнительный адрес вычисляется относительно регистра сегмента ds. Для регистра bp регистром сегмента служит регистр сегмента стека ss. Для изменения сегментных регистров, принятых по умолчанию, можно использовать операцию изменения префикса сегмента. Например, команда

mov es:[bx], dx

пересылает слово из регистра dx в ячейку памяти находящуюся в сегменте, адресуемом текущим содержимым сегментного регистра es (вместо ds) со смещением, находящемся в регистре bx.

Ввод строки с помощью функции OAh прерывания 21h

Для ввода строки с помощью функции 0Ah прерывания 21h область ввода должна быть описана специальным образом:

1 байт 1 байт Буфер для ввода символов

Первый байт содержит число, равное размеру буфера для ввода символов. Во втором байте будет храниться число, равное количеству введенных символов.

Вводимые символы будут сохраняться в буфере, начиная с третьего байта от начала описываемой области.

Итак, описать область для ввода строки из 10 символов можно как

Stroka   DB   11, ?, 11 DUP(?).

Длина строки и размер буфера задаются на единицу больше, так как один символ нужен для хранения числа 0dh – кода клавиши Enter.

Для облегчения доступа к каждой из описанных областей, описание можно разбить на 3 части:

MaxLength       DB 11
CurrentLehgth DB ?
Buffer                 DB 11 DUP(?)
;знак вопроса означает, что начальное
;значение данной ячейки памяти не определено

Вызов функции 0Ah выглядит так:

mov	AH, 0Ah	;номер функции заносим в регистр AH.
;в DX заносим адрес начала области ввода
mov	DX, OFFSET MaxLength	 
;таким же образом загружается адрес начала области ввода для Stroka
;mov 	DX, OFFSET Stroka
int	21h	;вызов прерывания

Рассмотрим план решения задач, представленных далее, на примере следующей задачи. С клавиатуры вводится строка s1. Необходимо скопировать из нее в строку s2 первый и последний символы и вывести на экран обе строки. Для этого в сегменте данных определим следующие области:

message	DBEnter the string:,10,13,$;приглашение к вводу
maxlength DB   11		;максимально допустимая длина строки
				;последним введенным символом
;будет символ с кодом 13 (0dh шестнадцатеричное – код клавиши Enter)
curlength DB   ?		;текущая длина строки равна количеству
				;введенных символов без учета кода Enter
s1	  DB   11 DUP(?)	;буфер, в который будут помещаться 
				;вводимые символы
s2	  DB   3 DUP(?)		;вторая строка: 2 позиции под буквы и одна
				;позиция под символ $ – признак конца 
				;строки для 9–ой функции
new_line  DB  10,13,$;строка, которая будет использоваться для 
;перевода курсора на новую строку

Далее программу можно составлять по следующему сценарию:

1. Выводим строку message на экран.
2. Вводим строку s1 на экран.
3. Копируем первый символ из s1 в s2 через регистр AL:

mov     AL, s1
mov     s2, AL

4. Помещаем в BX количество введенных символов:

mov      BL, curlength
mov      BH, 0

5. Копируем последний символ из s1 в s2 на вторую позицию через регистр AL:

mov      AL, s1[BX–1]
mov      s2+1,AL

6. Помещаем символ $ в конец строк s1 и s2:

mov s2+2,’$’
mov s1[bx],’$’

7. Выводим строку s1 на экран.
8. Выводим строку new_line.
9. Выводим строку s2 на экран.
10. Выводим строку new_line.
11. Завершаем программу с помощью функции 04ch прерывания 21h.

Задания

  1. Написать программу, соответствующую вашему варианту.
  2. Выполнить программу под управлением отладчика TD. Провести пошаговую трассировку программы, прослеживая на каждом шаге содержимое сегмента данных. Изучить изменение командного указателя IP и сегмента данных от шага к шагу выполнения программы.

Варианты задач

  1. Ввести строку s1 длиной не менее 10 символов. Скопировать в строку s2
    2–ой, 4–ый и 6–ой символы из строки s1. Вывести на экран строки s1 и s2.
  2. Ввести строку s1 длиной не менее 10 символов. Скопировать в строку s2
    10–ый, 5–ый и 2–ой символы из строки s1. Вывести на экран строки s1 и s2.
  3. Ввести строку s1 длиной не менее 10 символов. Скопировать в строку s2 каждый 3-ий символ из строки s1. Вывести на экран строки s1 и s2.
  4. Ввести строку s1 длиной не менее 10 символов. Скопировать в строку s2 все символы, стоящие на нечетных позициях из строки s1. Вывести на экран строки s1 и s2.
  5. Ввести строку s1 длиной не менее 10 символов. Скопировать в строку s2 все символы, стоящие на четных позициях из строки s1. Вывести на экран строки s1 и s2.
  6. Ввести строку s1 длиной не менее 10 символов. Скопировать в строку s2 три последних символа в прямом порядке из строки s1. Вывести на экран строки s1 и s2.
  7. Ввести строку s1 длиной не менее 10 символов. Скопировать из строки s1 в строку s2 три первых символа. Вывести на экран строки s1 и s2.
  8. Ввести строку s1 длиной не менее 10 символов. Скопировать из строки s1 в строку s2 три первых символа в обратном порядке. Вывести на экран строки s1 и s2.
  9. Ввести строку s1 длиной не менее 10 символов. Скопировать из строки s1 в строку s2 три последних символа в обратном порядке. Вывести на экран строки s1 и s2.
  10. Ввести строку s1 длиной не менее 10 символов. Скопировать из строки s1 в строку s2 последний символ три раза. Вывести на экран строки s1 и s2.
  11. Ввести строку s1 длиной не менее 10 символов. Скопировать из строки s1 в строку s2 предпоследний символ три раза и первый. Вывести на экран строки s1 и s2.
  12. Ввести строку s1 длиной не менее 10 символов. Скопировать из строки s1 в строку s2 пятый символ два раза и три раза второй. Вывести на экран строки s1 и s2.
  13. Ввести строку s1 длиной не менее 10 символов. Скопировать из строки s1 в строку s2 первые 3 символа два раза. Вывести на экран строки s1 и s2.
  14. Ввести строку s1 длиной не менее 10 символов. Скопировать из строки s1 в строку s2 второй и четвертый символы три раза. Вывести на экран строки s1 и s2.
  15. Ввести строку s1 длиной не менее 10 символов. Скопировать из строки s1 в строку s2 девятый символ – три раза, второй – два раза. Вывести на экран строки s1 и s2.
  16. Ввести строку s1 длиной не менее 10 символов. Скопировать из строки s1 в строку s2 последний и предпоследний символы два раза. Вывести на экран строки s1 и s2.

2. Этапы создания программы на языке Ассемблер. Вывод строки на экран

2. Этапы создания программы на языке Ассемблер. Вывод строки на экран

Цель работы:  получение знаний об основных правилах записи и структуре программ на языке Ассемблер для ПЭВМ типа IBM PC; приобретение практических навыков по составлению простейших программ на языке Ассемблер.

Теоретическая часть

Этапы создания программы

Разработка программы на  Ассемблере включает несколько шагов:

  • подготовку исходного кода программы,
  • ассемблирование программы (получение объектного кода),
  • компоновку программы (получение исполняемого файла программы),
  • отладку программы.

Текст программы записывается в один или несколько файлов. Имена файлов и их расширения могут быть произвольными, однако принято использовать для файлов, содержащих основную программу, расширение .asm, а для вспомогательных файлов, содержащих описание констант, новых типов, библиотеки функций, – расширение .inc.

Подготовленный текст программы необходимо преобразовать в машинные команды, которые могут быть выполнены микропроцессором. Это можно осуществить с помощью программ, называемых ассемблерами. После ассемблирования получают  объектные модули с расширением .obj. Ассемблирование можно выполнить с помощью компиляторов masm фирмы Microsoft или tasm фирмы Borland.

Процесс подготовки программы включает и процесс компоновки (редактирования связей). Работа компоновщика заключается в том, чтобы в каждом модуле определить и связать ссылки на неопределённые имена и обеспечить переместимость программы. Когда программа включает  несколько модулей, компоновщик объединяет их в один файл. В итоге будет получен выполняемый файл с расширением .exe или .com. Для этих целей можно использовать программу–компоновщик link фирмы Microsoft или tlink фирмы Borland.

Например, пусть файлы с исходными кодами называются prog1.asm и myLib.inc. В этом случае ассемблирование и компоновку можно выполнить следующими командами:

Таблица команд ассемблирования и компоновки

Microsoft Borland
Этап ассемблирования masm prog1.asm
masm myLib.inc
tasm prog1.asm
tasm myLib.inc
Этап компоновки link prog1.obj
link myLib.obj
tlink prog1.obj
tlink myLib.obj

 

Общая схема программы на языке Ассемблер

Строка в программе на Ассемблере может состоять из 4–х полей:

[метка:] команда [поле операндов] [;комментарий]

Метка используется для указания относительного адреса команды и служит для присвоения символического имени первому байту области памяти, в котором будет записан машинный эквивалент команды. Метки могут содержать:

  •  буквы от A до Z, причем Ассемблер не делает разницы между строчными и прописными буквами;
  • цифры от 0 до 9;
  • спец.символы – '?', '.'(только первый символ), '@'(коммерческое эт), '$', '_'.

Первым символом в метке должна быть буква или специальный символ. Максимальная длина метки – 31 символ.

Поле команды содержит её имя. Операнды определяют данные, регистры, символические имена (относительные адреса).

Например, команда mov ax, 4 заносит в регистр ax значение 4.

В поле операндов, если оно присутствует, могут быть один или два операнда. Между собой операнды отделяются запятой. В командах с двумя операндами первый - это приемник (destination), а второй – источник (source).

Комментарий начинается с символа ';'. Все символы справа от символа ';' до конца строки воспринимаются Ассемблером как комментарий.

Так как строчные и прописные символы в Ассемблере не различаются, то записи вида mov ah, 9 и MOV AH, 9 воспринимаются Ассемблером  одинаково.

Ниже представлены примеры оформления программ для компиляторов masm и tasm.

;Шаблон оформления программы в “стиле” masm
.model small	; директива описания модели памяти
; программа имеет модель памяти 
; типа small – один сегмент кода и один сегмент данных
.stack 100	; начало сегмента стека
.data	; начало сегмента данных
...	; определение данных
.code	; начало сегмента кода
...	; здесь можно включить текст подпрограмм и 
; данные, которые необходимо расположить 
; в сегменте кода
.startup	; точка начала выполнения программы
...	; текст программы
end	; директива окончания текста программы

 

;Шаблон оформления программы в “стиле” tasm
sstack	SEGMENT	para stack "stack" ;определение сегмента стека	
	DB	100 dup (?)		;область стека, не менее 32 слов
sstack 	ENDS				;конец сегмента стека
 
sdata	SEGMENT	para data		;определение сегмента данных
...					;здесь помещаются директивы 
;определения данных
sdata	ENDS				;конец сегмента данных
scode 	SEGMENT para "code"	;определение сегмента кода
ASSUME 	CS:scode, DS:sdata 	;указывает Ассемблеру, что сегмент scode будет
;адресоваться с помощью сегментного регистра CS, 
;а сегмент sdata – с помощью сегментного регистра DS. здесь можно
;включить текст подпрограмм и данные, которые необходимо расположить в 
;сегменте кода
start:					;точка входа в программу здесь
...					;помещается текст программы
scode	ENDS				;конец сегмента кода
END 	start				;директива окончания текста 
					;программы

Директивы определения сегмента делят исходную программу на сегменты. В программе на языке Ассемблер возможны четыре вида сегментов:

  • сегмент данных – используется для хранения переменных и констант;
  • сегмент стека – используется для хранения временных данных и адресов возврата из подпрограмм;
  • сегмент команд – в нем располагается код программы, в нем также могут располагаться подпрограммы и данные;
  • дополнительный сегмент данных.

По крайней мере, один сегмент – сегмент команд должен присутствовать в каждой программе.

Сегментный регистр ds должен содержать адрес сегмента, в котором описаны данные. Занести адрес в регистр можно, например, следующим образом:

	mov	ax, @data	; для masm
	mov	ds, ax
или	mov	ax, sdata	; для tasm
	mov	ds, ax

Задание

1. Изучить структуру программы на Ассемблере и основные требования к ней.

2. Разработать программу вывода строки “Hello World” на экран в стилях masm и tasm:

  • с использованием директивы db определить в сегменте данных строку ‘Hello World’,10,13,’$’ (Hi db  ‘Hello World’,10,13,’$’),
  • инициализировать регистр ds адресом сегмента данных,
  • с помощью функции 9 прерывания 21h вывести эту строку на экран
mov	ah, 9		;номер функции всегда помещается в регистр ah
mov	dx, offset Hi	;регистр dx содержит начальный адрес
;выводимой строки
int	21h		;вызов прерывания
  • завершить программу функцией 4Ch прерывания 21h
mov	ah, 4Ch
int	21h

3. С помощью текстового редактора набрать программу и записать ее на диск. Оттранслировать программу и получить объектный файл, листинг программы и исполняемый файл. Например, если исходный файл называется myLab1.asm, то с помощью команд

tasm myLab1.asm, ,

tlink myLab1.obj

получаются файлы myLab1.obj, myLab1.exe и myLab1.lst.

Изучить полученный листинг программы.

Translate Переводчик

Подписка на новости

SmartResponder.ru
Ваш e-mail: *
Ваше имя: *

Хостинг для Wordpress сайтов