Специальные регистры назначения
* IP - указатель команды.
* Flags Register (Флаговый Регистр) - определяет текущее состояние процессора.
IP регистр всегда работает вместе с регистром сегмента СS, и это указывает в настоящее время выполнение команды.
Flags Register (Флаговый Регистр), автоматически изменяется микропроцессором после математических операций, это позволяет определять тип результата, и определить состояние передачи управление к другим частям программы.
Вообще, Вы не можете непосредственно обращаться к этим регистрам.
Арифметическо-логическое устройство - выполняет арифметические и логические операции под воздействием устройства управления.
Регистры общего назначения размерностью в один байт обозначаются B, C, D, E, H, L. Они используются для хранения данных и промежуточных результатов вычислений, выполняемых с помощью арифметическо-логического устройства.
Аккумулятор - специальный регистр, обозначаемый А. При выполнении арифметических и логических операций служит источником одного из операндов и местом запоминания результата выполнения операции.
Регистр команд - регистр, в котором хранится код выполняемой команды. Этот регистр непосредственно пользователю недоступен. Это означает, что не существует команды, которая бы явным образом могла изменить его содержимое. После выполнения очередной команды в регистр команд автоматически записывается код следующей команды из ячейки оперативной памяти, адрес которой содержится в счетчике команд.
Счетчик команд - двухбайтовый (шестнадцатиразрядный) регистр, обозначаемый РС. Этот регистр хранит адрес следующей команды, которая должна быть выполнена вслед за предыдущей. Счетчик команд автоматически получает приращение хранимого в нем адреса в зависимости от того, какую по длительности команду (в один, два или три байта) микропроцессор считывает из памяти, указывая всегда на 1-й байт следующей команды. На содержимое этого регистра пользователь может повлиять только с помощью команд, изменяющих последовательное выполнение программы (например, команд безусловного перехода), а также с помощью некоторых специальных команд.
Указатель стека - двухбайтовый (шестнадцатиразрядный) регистр, обозначаемый SР. Этот регистр хранит адрес вершины стека. Стеком называется специально ориентированная область памяти, используемая для временного хранения данных или адресов. Особенностью работы стека является то, что число, записанное в стек последним, извлекается из него первым. Используя стек, легко в программах организовывать переходы, вызов подпрограмм и выполнение прерываний работы микропроцессора.
Флаговый регистр представляет собой набор флагов. Каждый флаг предназначен для хранения одного признака результата выполнения операции.
Большинство арифметических и логических команд затрагивает регистр состояния процессора (или Flags)
Микропроцессор 8086 содержит флаговый регистр, состоящий из следующих флагов:
Поскольку Вы можете видеть, что имеются 16 битов в этом регистре, каждый бит называется flag (флажком) и может принимать значение 1 или 0.
Carry Flag (Флажок Переноса) (CF) - этот флажок установлен в 1, когда там - переполнение без знака. Например, когда Вы добавляете, что байты 255 + 1 (результат не в диапазоне 0 ... 255). Когда не имеется никакого переполнения, этот флажок установлен в 0.
Zero Flag (Нулевой Флажок) (ZF) - этот флажок установлен в 1, когда результат нулевой. Для ни одного нулевой результат этот флажок не установлен в 0.
Sign Flag (Флажок Признака) (SF) - этот флажок установлен в 1, когда результат отрицательный. Когда результат положителен, что это установлено в 0. Фактически этот флажок берет значение наиболее существенного бита.
Overflow Flag (Флажок Переполнения) (ОF) - этот флажок установлен в 1, когда имеется переполнение числа со знаком. Например, когда вы добавляете, что байты 100 + 50 (результат не в диапазоне -128 ... 127).
Parity Flag (Флажок Четности) (PF) - этот флажок установлен в 1, когда там – четное число битов в результате, и 0, когда имеется нечетное число битов. Даже если результат - слово, только 8 младших битов проанализированы!
Auxiliary Flag (Вспомогательный Флажок) (AF) - этот флажок установлен в 1, когда имеется переполнение без знака для младшего бита, тетраэда (4 бита).
Interrupt enable Flag (Прерывание допускает Флажок) (IF)- когда этот флажок установлен в 1 микропроцессора, реагирует на прерывания от внешних устройств.
Direction Flag (Флажок направления) (DF) - этот флажок используется некоторыми командами, чтобы обработать цепочки данных, когда этот флажок установлен в 0 - обработка сделана вперед, когда этот флажок установлен в 1, обработка сделана назад.
Флаги всегда устанавливаются или сбрасываются автоматически после выполнения очередной команды, влияющей на флаги, в зависимости от результата операции. При этом флаг считается установленным, если флаговый разряд принимает значение 1, и сброшенным, если значение разряда 0. Состояния флагов используются в командах условного перехода.
Лекция 38
2.1. Краткие теоретические сведения
Директивы Типа Файла Вывода:
#MAKE_COM#
#MAKE_BIN#
#MAKE_BOOT#
#MAKE_EXE#
Вы можете вставлять эти директивы в исходном тексте, чтобы определить требуемый тип вывода файла. Только, если компилятор не может находить любую из этих директив, это спросит Вас относительно типа вывода перед созданием файла.
Описание типа Файла Вывода:
#MAKE_COM# - самый старый и самый простой формат исполняемого файла, такие файлы загружены 100h приставкой (256 байтов). Выберите Clean от меню New, если Вы планируете собирать COM файл. Директива Компилятора ORG 100h должна быть добавлена перед кодом. Выполнение всегда начинается от первого байта файла.
Поддержанный DOS и командной строкой Windows.
#MAKE_EXE# - более расширенный формат исполняемого файла. Не ограниченный размером и числом сегментов. Сегмент Стека должна быть определена в программе. Вы можете выбирать Шаблон EXE от меню New в создать простую программу EXE с определенными данными, стеком, и сегментами кода.
Точка входа (запуски выполнения) определены программистом.
#MAKE_BIN# - простой исполняемый файл. Вы можете определять значения всех регистров, сегментов и смещения для области памяти, где этот файл будет загружен. При загрузке "MY.BIN" файл к эмулятору это будет искать "MY.BINF" файл, и загружать "MY.BIN" файл к местоположению, указанному в "MY.BINF" файле, регистры также установлены, используя информацию о том файле (открывают этот файл в текстовом редакторе, чтобы редактировать или исследовать).
В случае, если эмулятор не способен найти "MY.BINF" файл, используются текущие значения регистра, и "MY.BIN" файл загружен в потоке CS:IP.
Выполнение начинается от значений в CS:IP.
Этот тип файла уникален к Emu8086 эмулятору.
".BINF файл автоматически создается компилятором, если находит директиву#MAKE_BIN#.
ПРЕДУПРЕЖДЕНИЕ! Любой существующий ".binf" файл записыватеся поверх!
#LOAD_SEGMENT=1234# #LOAD_OFFSET=0000# #AL=12# #AH=34# #BH=00# #BL=00# #CH=00# #CL=00# #DH=00# #DL=00# #DS=0000# #ES=0000# #SI=0000# #DI=0000# #BP=0000# #CS=1234# #IP=0000# #SS=0000##SP=0000#
Значения должны быть в HEX!
Когда не указаны эти значения, установлены по умолчанию:
LOAD_SEGMENT = 0100
LOAD_OFFSET = 0000
CS = ES = SS = DS = 0100
IP = 0000
Если LOAD_SEGMENT и LOAD_OFFSET не определены, то используются значения CSиIP и наоборот.
В случае, если значение загрузка смещения - не ноль (0000), ORG???? H должен быть добавлен к источнику a .BIN файл где???? H - смещение загрузки, это должно быть сделано, чтобы позволить компилятор, вычисляют правильные адреса.
Обработка Ошибок
Компилятор сообщает об ошибках, в отдельном информационном окне:
MOV DS, 100 - является не корректной командой, потому что регистры сегментов не могут быть установлены непосредственно, должны использоваться регистры общего назначения:
MOV AX, 100
MOV DS, AX
MOV AL, 300 - является корректной командой, потому что регистр AL имеет только 8 битов, и таким образом максимальное значение для этого - 255 (или 11111111b), и минимум - -128.
Компилятор делает несколько проходов, перед созданием правильного машинного кода, и если находит ошибку и не завершает требуемый число, проходит, это может показывать неправильным сообщениям об ошибках. Например:
#make_COM#ORG 100h MOV AX, 0MOV CX, 5m1: INC AXLOOP m1 ; not a real error!MOV AL, 0FFFFh ; error is here. RETСписок полученных ошибок:
(7) Условие выходит из диапазона!: LOOP m1
(9) параметров Wrong: MOV AL, 0FFFFh
(9) Операнд не соответствует: Второй операнд - более чем 8 битов!
Первое сообщение об ошибке (7) неправильно, компилятор не закончил вычислять смещения для меток, так что это предполагает, что смещение метки m1 - 0000, тот адрес находится из диапазона, потому что мы запускаем в 100h - смещении.
Делайте исправление в этой строке: MOV AL, 0FFFFh (AL не может иметь значение 0FFFFh). Это устраняет обе ошибки! Например:
#make_COM#ORG 100h MOV AX, 0MOV CX, 5m1: INC AXLOOP m1 ; same code no error! MOV AL, 0FFh ; fixed!RET
Для экономии компилируемого файла, компилятор также сохраняет 2 других файла, которые используются для Эмулятора, чтобы показать фактическому источнику, когда Вы выполняете это, и выбор соответствующие линии.
* *. ~ asm - этот файл содержит первоначальный исходный текст, который использовался, чтобы делать исполняемый файл.
* *.debug - этот файл имеет информацию, которая допускает линиям выбора эмулятора первоначального исходного текста при выполнении машинного кода.
*.symbol - Таблица Символа, содержит информацию, которая допускает, чтобы показать окну " Variables". Это - текстовый файл, так что Вы можете рассматривать его в любом текстовом редакторе.
*.binf - этот файл содержит информацию, которая используется эмулятором, чтобы загрузить файл BIN в указанном местоположении, и устанавливать регистр, оценивает предшествующее выполнение; (создавал только, если выполнимый - файл BIN.
Лекция 39
Доступ к памяти
Цель работы: изучение основ программирования микропроцессора, исследование выполнения отдельных команд и простых программ, использование переменных, массивов, прерываний, различных методов адресации в программах, запись программ в память микроЭВМ и их выполнение.
2.1. Краткие теоретические сведения
Чтобы обращаться к памяти, мы можем использовать эти четырех регистра: BX, SI, DI, BP.
Объединяя эти регистры внутри символа[], мы можем получить различные местоположения памяти. Эти комбинации - поддерживаемые способы адресации:
[BX + SI] [BX + DI] [BP + SI] [BP + DI] | [SI] [DI] d16 (variable offset only) [BX] | [BX + SI] + d8 [BX + DI] + d8 [BP + SI] + d8 [BP + DI] + d8 |
[SI] + d8 [DI] + d8 [BP] + d8 [BX] + d8 | [BX + SI] + d16 [BX + DI] + d16 [BP + SI] + d16 [BP + DI] + d16 | [SI] + d16 [DI] + d16 [BP] + d16 [BX] + d16 |
D8 - остается для 8 разрядного смещения.
D16 - остается для 16 разрядного смещения.
Смещение может быть непосредственное значение или возмещенное переменной, или даже оба. Это - до компилятора, чтобы вычислить одиночное непосредственное значение.
Смещение может быть внутри или вне символа [], компилятор производят тот же самый машинный код для обоих путей.
Смещение - значение число со знаком, так что это может быть оба положительны или отрицательны.
Вообще компилятор заботится относительно различия между d8 и d16, и производит требуемый машинный код.
Например, давайте принимать что DS = 100, BX = 30, SI = 70.
Следующий способ адресации: [BX + SI] + 25
Рассчитанный процессором физический адрес: 100 * 16 + 30 + 70 + 25 = 1725.
По умолчанию DS регистр сегмента используется для всех режимов, кроме тех с регистром BP, поскольку этот регистр сегмента используется с SS.
Имеется простой способ помнить все те возможные комбинации, использующие эту диаграмму:
Вы можете формировать все допустимые комбинации, беря только один элемент от каждого столбца или пропуская столбец, не беря что-нибудь от этого. Поскольку Вы видите BX, и BP никогда не идут вместе. SI и DI также не идут вместе. Имеется пример допустимого способа адресации: [BX+5].
Значение в регистре сегмента (СS, DS, SS, ES) называется "сегментом", и значение в регистре цели (BX, SI, DI, BP) называется "смещением".
Когда DS содержит значение, и SI содержит значение, это может быть также зарегистрировано как 1234:7890. Физический адрес будет 1234h * 10h + 7890h = 19BD0h.
Чтобы говорить компилятор относительно типа данных, должны использоваться эти приставки:
BYTE PTR - для байта.
WORD PTR - для слова (два байта).
Например:
BYTE PTR [BX]; доступ байта.
Или
WORDPTR [BX]; доступ слова.
Emu8086 поддерживает более короткие приставки также:
b. - для BYTE PTR
w. - для WORD PTR
Иногда компилятор может вычислять тип данных автоматически, но Вы не можете и не должны полагаться на это, когда один из операндов - непосредственное значение.
MOV команда
* Копирует второй операнд (источник) к первому операнду (адресат).
* Исходный операнд может быть непосредственное значение, регистр общего назначения или местоположение памяти.
* Регистр адресата может быть регистр общего назначения, или местоположение памяти.
* Оба операнда должны быть тот же самый размер, который может быть байт или слово.
Эти типы операндов поддержаны:
MOV REG, memory
MOV memory, REG
MOV REG, REG
MOV memory, immediate
MOV REG, immediate
REG: AX, BX, CX, DX, AH, AL, BL, BH, CH, CL, DH, DL, DI, SI, BP, SP.
memory (Память): [BX], [BX+SI+7], variable, etc...
immediate(Непосредственный): 5, -24, 3Fh, 10001101b, etc...
Поскольку сегментные регистры только эти типы MOV, поддержаны:
MOV SREG, memory
MOV memory, SREG
MOV REG, SREG
MOV SREG, REG
SREG: DS, ES, SS, and only as second operand: CS.
REG: AX, BX, CX, DX, AH, AL, BL, BH, CH, CL, DH, DL, DI, SI, BP, SP.
memory: [BX], [BX+SI+7], variable, etc...
Команда MOV не может использоваться, чтобы установить значение РЕГИСТ IP и CS.
Создадим небольшую программу, которая демонстрирует использование команды MOV и работу с памятью:
#MAKE_COM# ; инструктируйте компилятор делать COM файл.
ORG 100h ; директива, требуемая для программы COM.
MOV АX, 0B800h ; набор АX в значению hexadecimal B800h.
MOV DS, АX ; копируйте значение АX в DS.
MOV CL, 'A' ; набор CL к коду ASCII 'A', это - 41h.
MOV CH, 01011111b ; набор CH к двоичному значению.
MOV BX, 15Eh ; набор в BX -15Eh.
MOV [BX], CX ; копируйте содержание CX в память B800:015E
RET ; возвращение в операционную систему
Окно Эмулятора должно открыться с этой загруженной программой, щелкаем по кнопке [Single Step] и наблюдаем значения регистра.
Если используется комментарии ";", то любые символы после ";" игнорируется компилятором.
Вы должны увидеть, когда программа закончится:
Фактически вышеупомянутая программа пишет непосредственно видеопамяти, так что Вы можете видеть, что MOV - очень мощная команда.
Переменные
Переменная - местоположение памяти. Для программиста намного более легкое иметь некоторое значение сохраняться в переменной, названной "var1" тогда в адресе 5A73:235B, особенно, когда Вы имеете 10 или большее количество переменных.
Наш компилятор поддерживает два типа переменных: BYTE и WORD.
Синтаксис для переменной декларации:
имя DB Значение
имя DW Значение
DB - остается для, определяютБайт.
DW - остается для, определяютСлово.
Имя - может быть любой символ или комбинация цифры, хотя это должно начаться с символа. Возможно объявить, что неназванные переменные, не определяя имя (эта переменная будут иметь адрес, но никакого имени).
Значение - может быть любое числовое значение в любой поддержанной системе нумерации (hexadecimal, двоичный, или десятичном числе), или "?" Символ для переменных, которые не инициализированы.
Поскольку Вы вероятно знаете от части 2 об этой обучающей программе, команда MOV используется, чтобы копировать значения от источника до адресата.
Давайте видеть другой пример с командой MOV:
#MAKE_COM#ORG 100hMOV AL, var1MOV BX, var2RET ; stops the program. VAR1 DB 7var2 DW 1234h
Копируйте вышеупомянутый код Emu8086 исходному редактору, и нажмите клавишу F5, чтобы собирать и загрузить это в эмуляторе. Вы должны получить кое-что вроде:
Поскольку Вы видите, что это смотрит много подобно нашему примеру, за исключением того, что переменные заменены фактическими местоположениями памяти. Когда компилятор делает машинный код, это автоматически заменяет все переменные имена их смещениями. По умолчанию сегмент загружена в регистре DS (когда COM файлы загружены, значение регистра DS установлено в то же самое значение как регистр CS - регистр кода).
В памяти перечисляют первую строку - смещение, вторая строка - значение hexadecimal, третья строка - десятичное значение, и последняя строка - значение символа ASCII.
Компилятор не зависим от регистра, так что "VAR1" и "var1" относятся к одной и той же переменной.
Смещение VAR1 - 0108h, и полный адрес - 0B56:0108.
Смещение var2 - 0109h, и полный адрес - 0B56:0109, эта переменная - WORD, так что это занимает 2 BYTES. Принимается, что низкий байт сохранен в более низком адресе, столь 34h расположен перед 12h.
Вы можете видеть, что имеются некоторые другие команды после команды RET, это случается, потому что disassembler понятия не имеет относительно того, где запуски данных, только обрабатывает значения в памяти, и это понимает их как допустимые команды 8086 (мы изучим их позже).
Вы можете даже написать ту же самую программу, используя DB директиву только:
#MAKE_COM#ORG 100hDB 0A0hDB 08hDB 01h DB 8BhDB 1EhDB 09hDB 01h DB 0C3h DB 7 DB 34hDB 12h
Копируйте вышеупомянутый код Emu8086 исходному редактору, и нажмите клавишу F5, чтобы собирать и загрузить это в эмуляторе. Вы должны получить тот же самый демонстрационный код, и те же самые функциональные возможности!
Поскольку Вы можете предполагать, компилятор только преобразовывает источник программы к набору байтов, этот набор называется, машинный код, процессор понимает машинный код и выполняет это.
ORG 100h - директива компилятора (это сообщает компилятору, как обработать исходный текст). Эта директива очень важна, когда Вы работаете с переменными. Сообщает компилятору, что исполняемый файл будет загружен в смещении 100h (256 байтов), так что компилятор должен вычислить правильный адрес для всех переменных, когда это заменяет переменные имена их смещениями. Директивы никогда не преобразованы к любому реальному машинному коду.
Почему исполняемый файл загружен в смещении 100h? Операционная система сохраняет некоторые данные относительно программы в первых 256 байтах CS(сегмент кода), типа параметров командной строки и т.д.
Хотя это истинно только для COM файлов, EXE файлы загружены в смещении 0000, и вообще используют специальный сегмент для переменных. Мы будем говорить относительно EXE файлов позже.
Лекция 40
Массивы
Массивы могут быть замечены как цепочки переменных. Текстовая строка - пример массива байта, каждый символ представлен как значение кода ASCII (0 .. 255).
Имеются некоторые примеры определения массива:
a DB 48h, 65h, 6Ch, 6Ch, 6Fh, 00h
b DB 'Hello', 0
B - точная копия массива, когда компилятор видит, что строка внутри указывает это, автоматически преобразовывает это, чтобы установить байтов. Эта диаграмма показывает части памяти, где эти массивы объявлены:
Вы можете обращаться к значению любого элемента в массиве, использующем квадратные скобки, например:
MOV AL, a[3]
Вы можете также использовать любой из индекса памяти, регистрирует BX, SI, DI, BP, например:
MOV SI, 3
MOV AL, a[SI]
Если Вы должны объявить большой массив, Вы можете использовать оператор DUP.
Синтаксис для DUP:
число DUP (значение (я))
число - число дубликата, чтобы делать (любое постоянное значение).
Значение - выражение, что DUP дублирует.
Например:
C DB 5 DUP (9)
Является альтернативным путем объявления:
C DB 9, 9, 9, 9, 9
Еще один пример:
D DB 5 DUP (1, 2)
Является альтернативным путем объявления:
D DB 1, 2, 1, 2, 1, 2, 1, 2, 1, 2
Конечно, Вы можете использовать DW вместо DB, если это требуется, чтобы сохранить значения большее тогда 255, или меньшее тогда -128. DW не может использоваться, чтобы объявить строки!
Расширение DUP операнда не должно быть более чем 1020 символов! (Расширение последнего примера - 13 случайных работ), если Вы должны объявить, что огромный массив делит декларацию это на двух линиях (Вы получите одиночный огромный массив в памяти).
Дата добавления: 2016-07-05; просмотров: 3806;