Системное программирование на ассемблер
Системное программирование
Задание 1
Текст задания
Задание 1.1. Используя командные файлы, подготовьте к выполнению и запустите программы из примеров 1, 2 и 3. Убедитесь, что они выводят на экран нужный текст и успешно завершаются.
Задание 1.2. Заполните таблицы трассировки для программ вывода строки на экран из примеров 1, 2 и 3.
Таблица трассировки программы
Шаг |
Машинный код |
Команда |
Регистры |
Флаги |
||||||||
AX |
BX |
CX |
DX |
SP |
DS |
SS |
CS |
IP |
CZSOPAID |
|||
1 |
||||||||||||
2 |
||||||||||||
… |
Пример 1
Текст программы
stak segment stack ‘stack’ ;Начало сегмента стека
db 256 dup (?) ;Резервируем 256 байт для стека
stak ends ;Конец сегмента стека
data segment ‘data’ ;Начало сегмента данных
Hello db ‘Hello, World!$’ ;Строка для вывода
data ends ;Конец сегмента данных
code segment ‘code’ ;Начало сегмента кода
assume CS:code, DS:data, SS:stak ;Сегментный регистр CS будет ;указывать на сегмент команд,
;регистр DS — на сегмент данных, ;SS – на стек
start: ;Точка входа в программу start
;Обязательная инициализация регистра DS в начале программы
mov AX, data ;Адрес сегмента данных сначала ;загрузим в AX,
mov DS, AX ;а затем перенесем из AX в DS
mov AH,09h ;Функция DOS 9h вывода на экран
mov DX, offset Hello ;Адрес начала строки ‘Hello, ;World!’ записывается в регистр DX
int 21h ;Вызов функции DOS
mov AX,4C00h ;Функция 4Ch завершения ;программы с кодом возврата 0
int 21h ;Вызов функции DOS
code ends ;Конец сегмента кода
end start ;Конец текста программы с точкой ;входа
Текст командного файла
cls
tasm. exe task1.asm
tlink. exe /x task1.obj
task1
Таблица трассировки
Шаг |
Машинный код |
Команда |
Регистры |
Флаги |
||||||||
AX |
BX |
CX |
DX |
SP |
DS |
SS |
CS |
IP |
CZSOPAID |
|||
0000 |
0000 |
0000 |
0000 |
0100 |
489D |
48AD |
48BE |
0000 |
00000010 |
|||
1 |
B8BD45 |
mov ax, 48BD |
48BD |
0000 |
0000 |
0000 |
0100 |
489D |
48AD |
48BE |
0003 |
00000010 |
2 |
8ED8 |
mov ds, ax |
48BD |
0000 |
0000 |
0000 |
0100 |
48BD |
48AD |
48BE |
0005 |
00000010 |
3 |
B409 |
mov ah, 09 |
09BD |
0000 |
0000 |
0000 |
0100 |
48BD |
48AD |
48BE |
0007 |
00000010 |
4 |
BA0000 |
mov dx, 0000 |
09BD |
0000 |
0000 |
0000 |
0100 |
48BD |
48AD |
48BE |
000A |
00000010 |
5 |
CD21 |
int 21 |
09BD |
0000 |
0000 |
0000 |
0100 |
48BD |
48AD |
48BE |
000C |
00000010 |
6 |
B8004C |
mov ax, 4C00 |
4C00 |
0000 |
0000 |
0000 |
0100 |
48BD |
48AD |
48BE |
000F |
00000010 |
7 |
CD21 |
int 21 |
0192 |
000B |
F711 |
098D |
0106 |
2110 |
0192 |
0000 |
0000 |
10100011 |
Пример 2
Текст программы
.model small ;Модель памяти SMALL использует ;сегменты
;размером не более 64Кб
.stack 100h ;Сегмент стека размером 100h (256 ;байт)
.data ;Начало сегмента данных
Hello db ‘Hello, World!$’
.code ;Начало сегмента кода
start: ;Точка входа в программу start
;Предопределенная метка @data ;обозначает
;адрес сегмента данных в момент ;запуска программы,
mov AX, @data ;который сначала загрузим в AX,
mov DS, AX ;а затем перенесем из AX в DS
mov AH,09h
mov DX, offset Hello
int 21h
mov AX,4C00h
int 21h
end start
Текст командного файла
cls
tasm. exe task2.asm
tlink. exe /x task2.obj
task2
Таблица трассировки
Шаг |
Машинный код |
Команда |
Регистры |
Флаги |
||||||||
AX |
BX |
CX |
DX |
SP |
DS |
SS |
CS |
IP |
CZSOPAID |
|||
0000 |
0000 |
0000 |
0000 |
0100 |
489D |
48B0 |
48AD |
0000 |
00000010 |
|||
1 |
B8AF48 |
mov ax, 48AF |
48AF |
0000 |
0000 |
0000 |
0100 |
489D |
48B0 |
48AD |
0003 |
00000010 |
2 |
8ED8 |
mov ds, ax |
48AF |
0000 |
0000 |
0000 |
0100 |
48AF |
48B0 |
48AD |
0005 |
00000010 |
3 |
B409 |
mov ah, 09 |
09AF |
0000 |
0000 |
0000 |
0100 |
48AF |
48B0 |
48AD |
0007 |
00000010 |
4 |
BA0000 |
mov dx, 0000 |
09AF |
0000 |
0000 |
0000 |
0100 |
48AF |
48B0 |
48AD |
000A |
00000010 |
5 |
CD21 |
int 21 |
09AF |
0000 |
0000 |
0000 |
0100 |
48AF |
48B0 |
48AD |
000C |
00000010 |
6 |
B8004C |
mov ax, 4C00 |
4C00 |
0000 |
0000 |
0000 |
0100 |
48AF |
48B0 |
48AD |
000F |
00000010 |
7 |
CD21 |
int 21 |
0192 |
000B |
F711 |
098D |
0106 |
2110 |
0192 |
0000 |
0000 |
10100011 |
Пример 3
Текст программы
.model tiny ;Модель памяти TINY, в которой код, ;данные и стек
;размещаются в одном и том же сегменте ;размером до 64Кб
.code ;Начало сегмента кода
org 100h ;Устанавливает значение программного ;счетчика в 100h
;Начало необходимое для COM-программы,
;которая загружается в память с адреса ;PSP:100h
start:
mov AH,09h
mov DX, offset Hello
int 21h
mov AX,4C00h
int 21h
;===== Data =====
Hello db ‘Hello, World!$’
end start
Текст командного файла
cls
tasm. exe task3.asm
tlink. exe /x /t task3.obj
task3
Таблица трассировки
Шаг |
Машинный код |
Команда |
Регистры |
Флаги |
||||||||
AX |
BX |
CX |
DX |
SP |
DS |
SS |
CS |
IP |
CZSOPAID |
|||
0000 |
0000 |
0000 |
0000 |
FFFE |
489D |
489D |
489D |
0100 |
00000010 |
|||
1 |
B409 |
mov ah, 09 |
0900 |
0000 |
0000 |
0000 |
FFFE |
489D |
489D |
489D |
0102 |
00000010 |
2 |
BA0C01 |
mov dx, 010C |
0900 |
0000 |
0000 |
010C |
FFFE |
489D |
489D |
489D |
0105 |
00000010 |
3 |
CD21 |
int 21 |
0900 |
0000 |
0000 |
010C |
FFFE |
489D |
489D |
489D |
0107 |
00000010 |
4 |
B8004C |
mov ax, 4C00 |
4C00 |
0000 |
0000 |
010C |
FFFE |
489D |
489D |
489D |
010A |
00000010 |
5 |
CD21 |
int 21 |
0192 |
000B |
F711 |
098D |
0106 |
2110 |
0192 |
0000 |
0000 |
10100011 |
Контрольные вопросы
1. Запустите под управлением отладчика программу из примера 1. Как располагаются сегменты программы в памяти? Сопоставьте полученные данные с соответствующими размерами сегментов из листинга трансляции.
Ответ: CS – сегмент команд, DS – сегмент данных, SS – сегмент стека. CS = 48BEh, DS = 489Dh, SS = 48ADh
2. Что такое сегментный (базовый) адрес?
Ответ: Адрес ячейки памяти. Находится по формуле: база сегмента + смещение.
3. Почему перед началом выполнения программы из примера 1 содержимое регистра DS в точности на 10h меньше содержимого регистра SS?
Ответ: Адрес начала сегмента всегда кратен 16-ти (каждый сегмент должен начинаться на границе параграфа).
4. Почему в программе из примера 1 первая команда mov AX, data, начинающаяся с байта 0000 сегмента команд, занимает 3 байта? Какая еще команда занимает 3 байта?
Ответ: Так как здесь используется прямая адресация. Ещё 3 байта занимает команда mov dx, 0000.
5. Чему равен сегментный адрес сегмента команд программы из примера 2? Почему?
Ответ: 48ADh, так как используется модель памяти small.
6. Сравните содержимое регистра SP в программах из примера 2 и примера 3. Объясните, как получены эти значения.
Ответ: Во 2-м примере SP = 0100h, так как используется модель памяти small и стек располагается в первых 256 байтах сегмента памяти, а в 3-м – FFFEh, так как используется модель памяти tiny и сегменты кода, данных и стека находятся в одном сегменте размером 64 Кб.
7. Какие операторы называют директивами ассемблера? Приведите примеры директив.
Ответ: Директивы – это параметры, указывающие программе ассемблеру, каким образом следует объединять инструкции для создания модуля, который станет работающей программой. Примеры: ASSUME, SEGMENT.
8. Зачем в последнем предложении end указывают метку, помечающую первую команду программы?
Ответ: Для того, чтобы программа ассемблер поняла какая из подпрограмм закончена.
9. Как числа размером в слово хранятся в памяти и как они заносятся в 2-ух байтовые регистры?
Ответ: Они хранятся в памяти как шестнадцатеричное число и записываются справа налево. При занесении их в 2-х байтовые регистры байты меняются местами.
10.Как инициализируются в программе выводимые на экран текстовые строки?
Ответ: Сначала строка заносится в память также как и обычное число, а затем строка выводится на экран.
11.Что нужно сделать, чтобы обратиться к DOS для вывода строки на экран? Как DOS определит, где строка закончилась?
Ответ: Использовать оператор int 21h. В конец строки всегда добавляется символ $.
12.Программы, которые должны исполняться как. EXE и. COM, имеют существенные различия по:
o размеру,
o сегментной структуре,
o механизму инициализации.
Охарактеризуйте каждый из перечисленных пунктов.
Ответ: COM программы занимают меньше места в памяти и быстрее загружаются. В COM программах префикс программного сегмента, код программы, инициализированные данные и стек располагаются в одном сегменте. При запуске такой программы в начале строится PSP, занимающий 256 байт, далее располагается содержимое программы. Указатель стека устанавливается на конец сегмента.
EXE программы содержат сегменты кода, данных и стека. EXE файл загружается, начиная с адреса PSP:0100h. В процессе загрузки считывается информация EXE-заголовка в начале файла, при помощи которого загрузчик настраивает ссылки на сегменты в загруженном модуле, так как программа загружается в произвольный сегмент. После настройки ссылок управление передается загрузочному модулю к адресу CS:IP, извлеченному из заголовка EXE.