Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Формат регистр-память (и память-регистр)




КОП r1 A2

Здесь A – задаваемое в команде число (смещение) длиной 1 или 2 байта (заметим, что нулевое сме-щение иногда может не задаваться и совсем не занимать места в команде), M1 и M2 – так называемые регистры-модификаторы. Как сейчас будет показано, значение адреса второго операнда A2 вы-числяется по определённым правилам, поэтому этот адрес часто называют исполнительным (ex-ecutable) адресом.

Стоит отметить один факт. До сих пор в учебных ЭВМ адресом мы обычно называли физиче-ский номер ячейки в основной (оперативной) памяти компьютера. В нашей новой машине адресом принято называть смещение ячейки относительно начала того сегмента, в котором она в данный момент находится. Для обозначения же полного адреса будем употреблять термин физический ад-рес.

22. ают значение одного или двух байт из одного места памяти в другое. Для более компактного описания синтаксиса машинных команд введём следующие условные обозначения (с некоторыми из них мы уже знакомы): r8 – любой короткий регистр AH,AL,BH,BL,CH,CL,DH,DL; r16 – любой из длинных регистров AX,BX,CX,DX,SI,DI,SP,BP; m8, m16, m32 – операнды, расположенные в основной памяти длиной 1,2 и 4 байта; i8, i16, i32 – непосредственные операнды в самой команде длиной 1, 2 и 4 байта; SR – один из трёх сегментных регистров SS, DS, ES; CS – кодовый сегментный регистр. Общий вид команды пересылки в нашей двухадресной ЭВМ такой (как уже говорилось, после точки с запятой будем записывать, как это принято в Ассемблере, комментарий к команде): movop1,op2; op1:= op2 Команды пересылок не меняют флаги в регистре FLAGS. Как видим, в языке машины существу-ет несколько десятков команд пересылок различных форматов. Из приведённой выше таблицы сле-дует, что команды пересылок с кодом операции movбывают форматов RR, RX (и XR), RI и SI. Су-ществует также команда пересылки формата SS (память-память), но она имеет другое мнемониче-ское обозначение, является безадресной, и будет изучаться в главе, посвящённой так называемым строковым (или цепочечным) командам. Отметим также полезную команду обмена содержимым двух операндов xchgop1,op2; обмен значениями операндов: op1 ↔ op2.
Таблица допустимых операндов для этой команды: op1 op2
r8 r8, m8
m8 r8
r16 r16, m16
m16 r16

 

23. Изучение команд для выполнения арифметических операций начнём с самых распространённых команд сложения и вычитания целых чисел (вещественные числа, как уже говорилось, мы изучать не будем). Определим вид и допустимые операнды у этих двухадресных команд сложения и вычитания: КОПop1,op2, где КОП= add, sub, adc, sbb. Команды с кодами операций add(сложение) и sub(вычитание) выполняются по схеме: op1:= op1 ± op2 Команды с кодами операций adc(сложение с учётом флага переноса) и sbb(вычитание с учё-том флага переноса) имеют три операнда, два из которых задаются в команде явно, а третий по умолчанию является значением флага переноса CF: op1:= op1 ± op2 ± CF mulop2; беззнаковое умножение, imulop2; знаковое умножение, divop2; беззнаковое целочисленное деление, idivop2; знаковое целочисленное деление 24. Наличие большого количества форматов данных и команд в архитектурах некоторых современных ЭВМ приводит к дополнительным существенным трудностям при программировании на машинном языке. Для упрощения процесса написания программ для ЭВМ был разработан язык-посредник, названный Ассемблером,1 который, с одной стороны, должен допускать написание любых машинных команд, а с другой стороны – позволять автоматизировать и упростить процесс составления программ в машинном коде. Для перевода с языка Ассемблера на язык машины2 используется специальная программа-переводчик (транслятор), также называемая Ассемблером (от английского слова "assembler" – "сборщик"). В зависимости от контекста, если это не будет вызывать неоднозначности, в разных случаях под словом "Ассемблер" будет пониматься или сам язык программирования, или транслятор с этого языка. Рассмотрим, что, например, должна делать программа Ассемблер при переводе с языка Ассемб-лера на язык машины: • заменять мнемонические обозначения кодов операций на соответствующие машинные коды операций (например, для нашей учебной машины УМ-3, ВЧЦ → 12); • автоматически распределять память под хранение переменных, что позволяет программисту не заботиться о конкретном адресе переменной, если ему всё равно, где она будет расположена (внутри заданного сегмента при сегментной организации памяти); • подставлять в программе вместо имён переменных их значения (обычно значение имени переменной – это адрес этой переменной в некотором сегменте); • преобразовывать числа, написанные в программе в различных системах счисления во внутреннее машинное представление (в машинную систему счисления).    
  25. Во-первых, это так называемые машинно-зависимые системные программы, обычно они управляют различными устройствами компьютера (такие программы, как правило, называются драйверами). В этих системных программах используются специальные машинные команды, которые нет не-обходимости применять в обычных (или, как говорят прикладных) программах. Эти команды невозможно или весьма затруднительно задать в программе на языке высокого уровня. Кроме того, обычно от драйверов требуется, чтобы они были компактными и выполняли свою работу за минимально возможное время. Вторая область применения Ассемблера связана с оптимизацией выполнения больших про-грамм,1 которые требуют очень много времени для счёта. Часто программы-переводчики (трансляторы) с языков высокого уровня дают не совсем эффективную программу на машинном языке. Причина этого заключается в том, что такие программы могут иметь специфические особенности, которые не сможет учесть переводчик-компилятор. Итак, область применения языка Ассемблев в программировании непрерывно сокращается. В то же время, хорошему программисту совершенно необходимо ясно представлять, как написанные им конструкции на языках высокого уровня будут преобразовываться соответствующими компиляторами в машинный код. Умея мыслить в терминах языка низкого уровня, программист будет более ясно понимать, что происходит при выполнении его программы на ЭВМ, и как с учётом этого разрабатывать программы на языках высокого уровня 26. Изучение языка Ассемблера начнём с рассмотрения общей структуры программы на этом языке. Полная программа на языке Ассемблера состоит из одного или более модулей. Таким образом, Ас-семблер принадлежит к классу так называемых модульных языков. В таких языках вся программа может разрабатываться, писаться и отлаживаться как набор относительно независимых друг от друга программных частей – модулей. В каком смысле модуль является независимой единицей языка Ассемблер, мы выясним несколько позже, когда будем изучать тему "Модульное программирование". Наши первые программы будут содержать всего один модуль,2 но позже нами будут рассмотрены и простые многомодульные программы. Каждый модуль обычно содержит описание одного или нескольких сегментов памяти. Напомним, что в нашей архитектуре для работы программы каждая команда и каждая переменная должны располагаться в каких-либо сегментах памяти, иначе доступ к ним невозможен. Именно поэтому описание сегмента является важной синтаксической конструкцией языка Ассемблер. Как Вам уже должно быть известно, в младшей модели нашего семейства ЭВМ в каждый момент времени определены четыре активных (или текущих) сегмента памяти, на которые указывают соответствующие сегментные регистры с именами CS, DS, SS и ES. Таким образом, перед непосредственной работой с содержимым любого сегмента требуется установить на его начало определённый сегментный регистр, до этого нельзя ни писать в этот сегмент, ни читать из него. С другими сегментами, кроме этих четырёх текущих (если они есть в программе), работать в этот момент нельзя, при необходимости доступа к ним нужно менять (перезагружать) содержимое соответствующих сегментных регистров. Итак, модуль в основном состоит из описаний сегментов. В сегментах находятся все команды и области памяти, используемые для хранения переменных. Вне сегментов могут располагаться только так называемые директивы языка Ассемблер, о которых будем говорить немного ниже. Пока лишь отметим, что чаще всего директивы не определяют в программе ни команд, ни переменных (именно поэтому они и могут стоять вне сегментов).1 Описание каждого сегмента, в свою очередь, состоит из предложений (statement) языка Ассемблера. Каждое предложение языка Ассемблера занимает отдельную строчку программы, исключение из этого правила будет отмечено особо. Далее рассмотрим различные классы предложений Ассемблера.
26. Многострочные комментарии CPMMENT * <commetarii> * Команды.Почти каждому предложению языка Ассемблера этого типа будет соответствовать одна команде на языке машины (в редких случаях получаются две "тесно связанных" команды). Как уже отмечалось, вне описания сегмента такое предложение встречаться не может.   Резервирование памяти.Эти предложения также могут располагаться только внутри неко-торого сегмента. В том сегменте, где они записаны, резервируются области памяти для хранения пе-ременных. Это некоторый аналог описания переменных языка Паскаль. Заметим, что во многих учебниках такие предложения называют директивами резервирования памяти. Полные правила за-писи этих предложений надо посмотреть в учебнике [5], мы приведём лишь некоторые примеры с комментариями.
Предложение Количество памяти
A db? 1 байт
B dw? 2 байта (слово)
C dd? 4 байта (двойное слово)

 

 

Макрокоманды. Этот класс предложений Ассемблера относится к макросредствам языка, и будет подробно изучаться далее в нашем курсе. Пока надо лишь сказать, что на место макрокоман-ды при трансляции по определённым правилам подставляется некоторый набор (возможно и пустой) предложений Ассемблера

 

27. В большинстве современных компьютеров, в том числе и в нашем, по принципу Фон Неймана реализовано последовательное выполнение команд. В соответствие с этим принципом после выполнения текущей команды, если она не является командой перехода, счётчик адреса будет указывать на следующую (ближайшую с большим адресом) команду в оперативной памяти.2 Изменить последовательное выполнение команд можно с помощью переходов В большинстве современных компьютеров, в том числе и в нашем, по принципу Фон Неймана реализовано последовательное выполнение команд. В соответствие с этим принципом после выполнения текущей команды, если она не является командой перехода, счётчик адреса будет указывать на следующую (ближайшую с большим адресом) команду в оперативной памяти.2 Изменить поcледовательное выполнение команд можно с помощью переходов Переходы, вызванные выполнением центральным процессором специальных команд пере-ходов. • Переходы, которые автоматически выполняет центральный процессор при наступлении определённых событий в центральной части компьютера или в его периферийных устройст-вах (устройствах ввода/вывода).  
28. Рассмотрим сначала команды безусловного перехода, которые всегда передают управление в указанную в них точку программы. На языке Ассемблера все эти команды записываются в виде jmpop1jmp shortL Ясно, что об этом следует заботиться в основном при острой нехватке оперативной памяти для программы.1 Для явного указания дальнего перехода на метку в другом сегменте памяти, програм-мист должен использовать оператор far ptr, например: jmp far ptrL Приведём фрагмент программы с различными видами команд безусловного перехода, в этом фрагменте описаны два кодовых сегмента (для иллюстрации дальних переходов) и один сегмент данных (для команд косвенного перехода): 1 Например, это может быть необходимо при написании драйверов операционных систем или встроен-ных программ для управления различными устройствами (стиральными машинами, видеомагнитофонами и т.д.), либо программ для автоматических космических аппаратов, где память относительно небольшого объёма, т.к. должна быть особой, способной выдерживать сильное космическое излучение. movds,ax; загрузка сегментного регистра DS L2: jmp far ptrL1; дальний прямой абсолютный переход, op1=i32=seg:off jmpL1; ошибкат.к. без far ptr jmpL2; близкий относительный переход, op1=i8 или i16 jmpA1; близкий абсолютный косвенный переход, op1=m16 15 jmpA2; дальний абсолютный косвенный переход, op1=m32 jmpbx; близкий абсолютный косвенный переход, op1=r16 jmp[bx]; ошибка, нет выбора между: op1=m16 или op1=m32 movbx,offsetA2 jmp dword ptr[bx]; дальний абсолютный косвенный переход op1=m32 ... code2 ends   29 Все команды условного перехода в нашей архитектуре выполняются по схеме, которую на Пас-кале можно записать как if<условие перехода> then gotoL и производят близкий короткий относительный прямой переход, если выполнено некоторое ус-ловие перехода, в противном случае продолжается последовательное выполнение команд програм-мы. На Паскале такой переход чаще всего задают в виде условного оператора: ifop1 <отношение> op2 then gotoL где <отношение> – один из знаков операций отношения = (равно), <> (не равно), > (больше), < (меньше), <= (меньше или равно), >= (больше или равно). Если обозначить rez=op1–op2, то этот оператор условного перехода Паскаля можно записать в эквивалентном виде сравнения с нулём: ifrez <отношение> 0 then gotoL В нашей архитектуре все машинные команды условного перехода, кроме одной, вычисляют ус-ловие перехода, анализируя один, два или три флага из регистра флагов, и лишь одна команда ус-ловного перехода вычисляет условие перехода, анализируя значение регистра CX. Команда условного перехода в языке Ассемблера имеет такой вид: j<мнемоника перехода>i8; IP:= (IP + i8)mod 216 Мнемоника перехода (это от одной до трёх букв) связана со значением анализируемых флагов (или регистра CX), либо со способом формирования этих флагов. Чаще всего программисты фор-мируют нужные флаги, проверяя отношение между двумя операндами op1 <отношение> op2, для чего выполняется команда вычитания или команда сравнения. Команда сравнения имеет мнемони-ческий код операции cmpи такие же допустимые форматы операндов, как и команда вычитания: cmpop1,op2. Пусть, например, надо реализовать на Ассемблере условный оператор языка Паскаль ifX>Y then gotoL Соответствующий фрагмент на языке Ассемблера, реализующий этот оператор для знаковых величин X,Y: X dw? Y dw? ... movax,X cmpax,Y jgL ... L:
30. Например, цикл языка Паскаль с предусловием whileX<0 doS для целой знаковой пере-менной X можно реализовать в виде следующего фрагмента на Ассемблере: L: cmpX,0; Сравнить X с нулём jgeL1 ; Здесь будет оператор S jmpL L1:... Аналогично, оператор цикла с постусловием repeatS1; S2;... Sk untilX<0 можно реализовать в виде такого фрагмента на Ассемблере: L:; S1 ; S2 ... ; S kcmpX,0; Сравнить X с нулём jgeL ... В этих примерах мы считаем, что тело цикла по длине не превышает примерно 120 байт (это 30-40 машинных команд). Как видим, цикл с постусловием требует для своей реализации на одну команду (и на одну метку) меньше, чем цикл с предусловием Стеком в архитектуре нашего компьютера называется сегмент памяти, на начало которого указывает сегментный регистр SS (таким образом, стек в машине есть всегда). При работе программы в регистр SS можно последовательно загружать адреса начал разных сегментов, поэтому иногда говорят, что в программе несколько стеков. Однако в каждый момент стек только один – тот, на который сейчас указывает регистр SS. Именно он и будем далее иметься в виду. В нашей архитектуре стек хранится в сегменте памяти в перевёрнутом виде: начало сегмента (с меньшими адресами) является концом стека, а конец сегмента (с бoльшими адресами) – началом стека. Кроме начала и конца, у стека есть текущая позиция – вершина стека, её смещение от начала сегмента стека всегда записано в регистре SP (Stack Pointer). Следовательно, как мы уже знаем, физический адрес вершины стека можно получить по формуле Афиз = (SS*16 + SP)mod 220. Стек есть аппаратная реализация абстрактной структуры данных стек. В этой реализации в вершину стека можно записывать (и, соответственно, читать из неё) только машинные слова, команды чтение и запись в стек байтов в архитектуре младших моделях этого компьютера не предусмотрены. Это, конечно, не значит, что в стеке нельзя хранить байты, двойные слова и т.д., просто нет машинных команд для записи в вершину стека и чтения из вершины стека данных этих форматов. Наличие стека не отменяет для нашего компьютера принципа Фон Неймана однородности памяти, поскольку одновременно стек является и просто сегментом оперативной памяти и, таким образом, возможен обмен данными с этой памятью с помощью обычных команд (например, команд пересылки mov   В соответствие с определением машинного стека последнее записанное в него слово будет храниться в вершине стека, и читаться из стека первым. Это так называемое правило "последний пришёл – первый вышел" (английское сокращение LIFO – Last In First Out). Вообще говоря, это же правило можно записать и как "первый пришёл – последний вышел" (английское сокращение FILO – First In Last Out). В литературе встречаются оба этих правила и их сокращения. Будем изображать стек в нашей архитектуре "растущим" снизу-вверх, от конца к началу сегмента стека. Как следствие получается, что конец стека фиксирован и будет расположен на рисунках снизу, а вершина двигается вверх (при записи в стек) и вниз (при чтении из стека). В любой момент времени регистр SP указывает на вершину стека – это последнее слово, записанное в стек Обычно для резервирования памяти под стек на языке Ассемблера описывается специальный сегмент стека. В наших предыдущих программах мы делали это таким образом: stack segment stack dw64 dup(?) stack ends Имя сегмента стека и способ резервирования памяти может быть любым, например, стек такого же размера можно описать так: st_1 segment stack db128 dup(?) st_1 ends То, что этот сегмент будет при запуске программы на счёт использоваться именно как началь-ный сегмент стека, указывает не имя стека, а его параметр stackв директиве segment. Этот пара-метр является служебным словом языка Ассемблера и, вообще говоря, не должен употребляться ни в каком другом смысле.1  
8/ В УМ-3 первичной загрузкой программы в память и формированием начальных значе-ний регистров в устройстве управления занимается устройство ввода. Для этого на устройстве ввода имеется специальная кнопка ПУСК (☺). При нажатии этой кнопки устройство вводасамостоятельно (без сигналов со стороны устройства управления, которое ещё не функционирует) выполняет следующую последовательность действий: 1. Производит ввод расположенного на устройстве ввода массива машинных слов в память, начиная с первой ячейки; этот массив машинных слов заканчивается специальным при-знаком конца ввода. 2 2. РА:= 1; первой будет выполняться команда из ячейки а номером один. 3. w:= 0; начальное значение признака результата нулевое. 4. Err:= 0; признак ошибки сбрасывается (устанавливается равным false).  

 




Поделиться с друзьями:


Дата добавления: 2015-06-27; Просмотров: 673; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.02 сек.