Материал: 1117

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

datasg ends

codesg segment para ‘Code’

mov ax,0bad4h ; загрузить в ax шестнадцатеричную константу

. . . ; (первый 0 показывает, что это константа) mov ax,bad4h ; загрузить ax из переменной в памяти bad4h

; (отсутствие 0 в качестве первого символа показывает, что это метка)

. . .

codesg ends

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

Числа с плавающей точкой могут обозначаться двумя способами (см.

уч. пос., ч.4).

Чтобы показать, что число является десятичным, в качестве суффикса можно использовать букву d. Наконец, могут использоваться символьные константы, при этом символы заключаются в одиночные или двойные кавычки. Значением символа является его значение кода ASCII. Например, все следующие строки загружают в регистр al значение кода ASCII

символа А [1, с. 559].

 

mov

al,65

; 65 = 41h

mov

al,41h

 

mov

al,'A'

; ASCII код символа А = 41h

mov

al,"A"

; ASCII код символа А = 41h

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

4.50. Инициализированные данные

Директивы определения данных db, dw, dd, dq и dt позволяют определить переменные в памяти различного размера: один байт (db), два байта, т.е. одно слово (dw), четыре байта, т.е. двойное слово (dd), восемь байтов, т.е. одно учетверенное слово (dq) и десять байтов (dt).

Например:

datasg segment para ‘Data’

ByteVar db 'Z'

; 1

байт

WordVar dw 101b

; 2

байта (1 слово)

DwordVardd 2BFh

; 4

байта (1 двойное слово)

QwordVar dq 307o

; 8

байтов (1 учетверенное слово)

TwordVardt 100

; 10 байтов

datasg ends

codesg segment para ‘Code’

. . .

mov ah,2 ; функция DOS вывода на дисплей

56

mov dl,ByteVar ; символ, который нужно вывести на экран int 21h

mov ax,WordVar

. . .

add word ptr DwordVar,ax adc word ptr DwordVar+2,dx

. . .

codesg ends

Здесь определяются пять переменных памяти и показывается, как некоторые из таких переменных можно использовать.

4.51.Инициализация массивов

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

SampleArrray dw 0, 1, 2, 3, 4

создает массив из пяти элементов с именем SampleArray, элементы которого имеют размер в слово. В директивах определения данных можно использовать любое число значений, умещающееся на строке.

Если нужно определить массив, который слишком велик и не вмещается на одной строке, нужно добавить несколько строк. Метку в директиве определения данных указывать необязательно. Например, по директивам:

SquareArray dd 0, 1, 4, 9, 16 dd 25, 36, 49, 64, 81

dd 100, 121, 144, 169, 196

создается массив элементов размером в двойное слово с именем SquareArray, состоящий из квадратов первых 15 целых чисел.

Ассемблер позволяет определить блок памяти, инициализированный указанным значением, с помощью операции dup. Например,

BlankArraydw 100h dup (0)

Здесь создается массив BlankArray, состоящий из 256 слов (подругому: 100h), инициализированных значением 0. Аналогично директива:

ArrayOf_A db 92 dup ('A')

создает массив из 92 байтов, и каждый инициализирован символом A.

4.52.Инициализация строк символов

Строку символов можно определить следующим образом:

Stringdb 'A', 'B', 'C', 'D'

Предусмотрена также удобная сокращенная форма:

String db 'ABCD'

Чтобы переместиться к левому краю следующей строки, нужно вывести символы "возврат каретки/перевод строки". Например:

57

stacksg segment para ‘Stack’ db 256 dup (0)

stacksg ends

datasg segment para ‘Data’

String1 db

'Line1','$'

 

String2 db

'Line2','$'

 

String3 db

'Line3','$'

 

datasg ends

 

codesg segment para ‘Code’

ProgramStart:

 

mov ax,datasg

 

mov ds,ax

 

mov ah,9

 

; функция DOS печати строки

mov dx,offset String1

; печатаемая строка

int 21h

 

; вызвать DOS для печати строки

mov dx, offset String2

; печатаемая строка

int 21h

 

; вызвать DOS для печати строки

mov dx, offset String3

; печатаемая строка

int 21h

 

; вызвать DOS для печати строки

mov ah,4ch

; функция DOS завершения программы

int 21h codesg ends

end ProgramStart

Программа печатает следующее:

Line1Line2Line3

Однако если в конце каждой строки добавить символы "возврат каретки/перевод строки":

String1 db 'Line1',0dh,0ah,'$' String2 db 'Line2',0dh,0ah,'$' String3 db 'Line3',0dh,0ah,'$'

то вывод будет выглядеть следующим образом:

Line1

Line2

Line3

4.53. Инициализация выражений и меток

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

58

Можно также использовать: выражения:

TestVar dw ((924/2)+1); TestVar инициализируется значением 463

и метки:

datasg segment para ‘Data’

db 1,2,3,4,5,6,7,8,9,10,10,9,8,7,6,5,4,3,2,1

Buffer dw 16 dup (0) ; область памяти из 16-ти нулевых слов

BufferPointer dw Buffer datasg ends

Начальное значение BufferPointer представляет собой смещение Buffer в сегменте datasg, а не значение 0, которое хранится в переменной Buffer. В результате этого и инструкция:

mov ax,offset Buffer

и инструкция:

mov ax,BufferPointer

загрузят в регистр ax одно и то же значение (смещение переменной Buffer, которое в приведенном выше примере равно 20, т.к. в сегменте данных перед областью данных с меткой Buffer располагается 20 байтов данных).

В выражениях определения данных допускается использовать метки. Например, переменная WordArrayLength инициализируется значением длины (в байтах) WordArray:

datasg segment para ‘Data’

WordArray dw 50 dup (0); массив из 50-ти нулевых слов

WordArrayEnd label word

WordArrayLength dw (WordArrayEnd - WordArray);длина = 100 datasg ends

Если требуется вычислить длину переменной WordArray в словах, а не в байтах, это можно сделать, просто разделив длину в байтах на 2:

WordArrayLength dw (WordArrayEnd - WordArray) / 2

4.54. Неинициализированные данные

Иногда нет смысла присваивать переменной памяти начальное значение. Тогда применяют знак вопроса (?). Например:

KeyBuffer db 10 dup (?)

В данной строке резервируется 10 байтов памяти, начиная с метки KeyBuffer, но этим байтам не присваивается никакого конкретного значения.

Конечно, при использовании неинициализированной переменной ее нужно инициализировать в своей программе перед тем, как использовать. Например, было бы ошибочным использовать содержимое KeyBuffer до

59

того, как этот массив будет заполнен, так как находящиеся в KeyBuffer начальные значения не определены.

4.55. Именованные ячейки памяти

Кроме присвоения имени ячейке памяти с помощью метки, предшествующей директиве определения данных (например, db), можно присваивать имя ячейке директивой label, которая позволяет определить имя метки и ее тип, не определяя при этом данные. Например, в предыдущем примере массив KeyBuffer можно определить так:

KeyBuffer label byte db 10 dup (?)

Типы меток, которые можно определить с помощью label, включают в себя: byte, word, dword, qword, tbyte, proc, near, far, unknown и др.

Типы byte (байт), word (слово), dword (двойное слово), qword (учетверенное слово) и tbyte (десять байтов) говорят сами за себя, определяя, соответственно, 1-, 2-, 4-, 8- и 10-байтовые элементы данных. Приведем пример инициализации переменной, как пары байтов, но обращения к ней, как к слову:

datasg segment para ‘Data’ WordVar label word

db 1,2 datasg ends

codesg segment para ‘Code’

. . .

mov ax,[WordVar]

. . .

Когда эта программа выполняется, в регистр al загружается 1 (первый байт WordVar), а в регистр ah – значение 2.

Ключевые слова near и far используются в программе для выбора типа вызова или перехода, необходимого для достижения определенной метки. Например, в программе:

codesg segment para ‘Code’

. . .

FarLabel label far NearLabel label near

mov ax,1

. . .

jmp FarLabel

. . .

jmp NearLabel

. . .

60

Источник: https://studfile.net/preview/16407174/