CodeNet / Языки программирования / Ассемблер / СПРАВОЧНИК по системе программирования ТУРБО АССЕМБЛЕР 2.0
СПРАВОЧНИК по системе программирования ТУРБО АССЕМБЛЕР 2.0
Именованные ячейки памяти ----------------------------------------------------------------- До сих пор мы видели только, как можно присваивать имена ячейкам памяти с помощью метки, предшествующей директиве опреде- ления данных (например, DB). Другой удобный способ присваивать имя ячейке памяти предоставляет директива LABEL. Директива LABEL позволяет вам определить как имя метки, так и ее тип, не определяя при этом данные. Вот, например, еще один способ, с помощью которого можно определить в предыдущем примере массив KeyBuffer: . . . KeyBuffer LABEL BYTE DB 10 DUP (?) . . . Типы меток, которые можно определить с помощью директивы LABEL, включают в себя: BYTE PWORD FAR WORD QWORD PROC DWORD TBYTE UNKNOWN FWORD NEAR Типы BYTE (байт), WORD (слово), DWORD (двойное слово), PWORD, QWORD и TBYTE говорят сами за себя, определяя, соответст- венно, 1-, 2-, 4-, 6-, 8- и 10-байтовые элементы данных. Приведем пример инициализации переменной памяти, как пары байт, и обраще- ния к ней, как к слову: . . . .DATA WordVar LABEL WORD DB 1,2 . . . .CODE . . . mov ax[WordVar] . . . Когда эта программа выполняется, в регистр AL загружается 1 (первый байт WordVar), а в регистр AH - значение 2. Ключевые слова NEAR и FAR используются в программе для выбо- ра типа вызова или перехода, необходимого для достижения опреде- ленной метки. Например, в программе: . . . .CODE . . . FarLabel LABEL FAR NearLabel LABEL NEAR mov ax,1 . . . jmp FarLabel . . . jmp NearLabel . . . первая инструкция JMP представляет собой переход дальнего типа (загружаются оба регистра CS и IP), так как это переход на метку типа FAR, а второй переход имеет ближний тип (загружается только регистр IP), так как это переход на метку типа NEAR. Заметим, что обе метки FarLabel и NearLabel описывают один и тот же адрес (ад- рес инструкции MOV), но позволяют вам переходить на него различ- ными способами. Когда вы используете упрощенные директивы определения сег- ментов, то директива PROC - это удобный способ определить метку нужного типа (ближнюю или дальнюю) для текущей модели кода. Когда используется сверхмалая, малая или компактная модель памяти, то LABEL PROC - это то же самое, что LABEL FAR. Это означает, что если вы измените модель памяти, вы также можете автоматически из- менить определенные метки. Например, в программе: DOSSEG .MODEL small . . . .CODE . . . EntryPoint LABEL PROC . . . метка EntryPoint имеет ближний тип, но если вы измените модель памяти на большую, то это будет метка дальнего типа. Обычно для определения тех точек входа, которые вы хотели бы изменить при изменении модели памяти вместо директивы LABEL используют дирек- тиву PROC (см. далее раздел "Подпрограммы"), однако иногда требу- ется иметь несколько точек входа в подпрограмму, и вам потребует- ся директива LABEL. Наконец, мы подошли к директиве LABEL UNKNOWN. Ключевое сло- во UNKNOWN (неизвестно) - это просто способ указать, что вы не уверены насчет типа данных используемой метки. Если вы знакомы с языком Си, то UNKNOWN аналогично типу языка Си void. В качестве примера UNKNOWN предположим, что у вас имеется переменная памяти TempVar, к которой иногда нужно обращаться, как к байту, а иногда - как к слову. С помощью LABEL UNKNOWN это делается в следующей программе: . . . .DATA TempVar LABEL UNKNOWN DB ?,? . . . .CODE . . . mov [TampVar],ax . . . add di,[TempVar] . . . Перемещение данных ----------------------------------------------------------------- Итак, вы уже получили довольно обширное представление о при- роде языка Ассемблера, основных его концепциях и структуре прог- рамм на Ассемблере. Теперь, когда вы усвоили основы, можно сосре- доточить внимание на инструкциях языка Ассемблера, образующих ту часть программы на Ассемблере, которая и указывает процессору 8086 на необходимость выполнения конкретных действий. Давайте начнем с самой основной операции Ассемблера - перемещения данных. Данные в процессоре 8086 перемещаются с помощью инструкции MOV. В действительности MOV (от слова переместить) - это не сов- сем удачное название данной инструкции. Более удачным было бы название COPY (копировать), так как инструкция MOV на самом деле записывает копию операнда-источника в операнд-приемник. Например, инструкции: . . . mov ax,0 mov bx,9 mov ax,bx . . . сначала записывают в регистр AX константу 0, затем в регистр BX записывается константа 9, и, наконец, содержимое BX копируется в AX, как показано на следующей схеме: После mov ax,0: ------------------------------- AX | 0 | ------------------------------- ------------------------------- BX | ? | ------------------------------- После mov bx,9: ------------------------------- AX | 0 | ------------------------------- ------------------------------- BX | 9 | ------------------------------- После mov ax,bx0: ------------------------------- AX | 9 | ------------------------------- ------------------------------- BX | 9 | ------------------------------- Заметим, что значение 9 не перемещается из BX в AX, оно просто копируется из регистра BX в регистр AX. В инструкции MOV можно использовать почти любую пару операн- дов, что имеет смысл за исключением того случая, когда в качестве операнда используется сегментный регистр (этот случай мы обсудим далее в разделе "Обращение к сегментным регистрам"). В качестве операнда-источника (правого операнда) инструкции MOV можно ис- пользовать следующее: константу, выражение, при вычислении кото- рого получается константа, общий регистр или ячейку памяти, дос- тупную с помощью одного из режимов адресации, описанного в разде- ле "Режимы адресации памяти". В качестве операнда-приемника (ле- вого операнда) инструкции MOV может использоваться общий регистр или ячейка памяти.