CodeNet / Языки программирования / Ассемблер / СПРАВОЧНИК по системе программирования ТУРБО АССЕМБЛЕР 2.0
СПРАВОЧНИК по системе программирования ТУРБО АССЕМБЛЕР 2.0
Инициализация строк символов
-----------------------------------------------------------------
Рассмотрим теперь создание строк символов. Символы представ-
ляют собой допустимые операнды директив определения данных, поэ-
тому строку символов можно определить следующим образом:
String DB 'A', 'B', 'C', 'D'
В Турбо Ассемблере в этом случае предусмотрена также удобная
сокращенная форма:
String DB 'ABCD'
Если вы хотите использовать вид строки, принятый в языке Си
(которая заканчивается нулевым байтом), вы должны явно указать в
конце строки нулевой байт. Аналогично, если вы хотите завершить
строку символами возврата каретки и перевода строки, их также
нужно включить в строку. В следующем примере определяется тексто-
вая строка, за которой следует символ возврата каретки, символ
перевода строки и нулевой байт:
HelloString DB 'Привет!',0dh,0ah,0
Чтобы переместиться к левому краю следующей строки, вы
должны вывести пару символов "возврат каретки/перевод строки".
Например, программа:
DOSSEG
.MODEL SMALL
.STACK 100h
.DATA
String1 DB 'Line1','$'
String2 DB 'Line2','$'
String3 DB 'Line3','$'
.CODE
ProgramStart:
mov ax,@data
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
END ProgramStart
печатает следующее:
Line1Line2Line3
Однако если в конце каждой строки вы добавите пару символов
"возврат каретки/перевод строки":
String1 DB 'Line1','$',0dh,0ah,'$'
String2 DB 'Line2','$',0dh,0ah,'$'
String3 DB 'Line3','$',0dh,0ah,'$'
то вывод будет выглядеть следующим образом:
Line1
Line2
Line3
Инициализация выражений и меток
-----------------------------------------------------------------
Начальное значение инициализированной переменной должно
представлять собой константу, но это не обязательно должно быть
число. Можно также использовать выражения:
TestVar DW ((924/2)+1)
а также метки:
.
.
.
.DATA
Buffer DW 16 DUP (0)
BufferPointer DW Buffer
.
.
.
Когда в качестве операнда директивы определения данных ис-
пользуется метка, то используется значение самой метки, а не зна-
чение, записанное по этой метке. В последнем примере начальное
значение BufferPointer представляет собой смещение Buffer в сег-
менте .DATA, а не значение 0, которое хранится в переменной
Buffer (как если бы для инициализации BufferPointer использова-
лось OFFSET Buffer). Другими словами, с учетом такой инициализа-
ции BufferPointer, и инструкция:
mov ax,OFFSET Buffer
и инструкция:
mov ax,[BufferPointer]
загрузят в регистр AX одно и то же значение (смещение переменной
Buffer).
В выражениях определения данных допускается использовать
метки. Например, в следующем фрагменте программы переменная
WordArrayLength инициализируется значением длины (в байтах)
WordArray:
.
.
.
.DATA
WordArray DW 50 DUP (0)
WordArrayEnd LABEL WORD
WordArrayLength DW (WordArrayEnd - WordArray)
.
.
.
Если вы хотите вычислить длину переменной WordArray в сло-
вах, а не в байтах, это можно сделать, просто разделив длину в
байтах на 2:
WordArrayLength DW (WordArrayEnd - WordArray) / 2
Неинициализированные данные
-----------------------------------------------------------------
Иногда нет смысла присваивать переменной памяти начальное
значение. Предположим, например, что ваша программа считывает
следующие 10 набранных на клавиатуре символов и записывает их в
массив с именем KeyBuffer:
.
.
.
mov cx,10 ; число символов, которые
; требуется считать
mov bx,OFFSET KeyBuffer ; символы будут
; сохранены в KeyBuffer
GetKeyLoop:
mov ah,1 ; функция DOS ввода с
; клавиатуры
int 21h ; получить следующий
; нажатый символ
mov [bx],al ; сохранить символ
inc cx ; ссылка на ячейку
; памяти для следующего
; символа
loop GetKeyLoop
.
.
.
Инициализировать KeyBuffer можно следующим образом:
KeyBuffer DB 10 DUP (0)
но смысла в этом немного, так как начальные значения массива
KeyBuffer будут немедленно перезаписаны в цикле GetKeyLoop. Все,
что здесь в действительности нужно - это определить переменную в
памяти, как неинициализированную. Турбо Ассемблер предусматривает
такую возможность с помощью символа "знак вопроса" (?).
Вопросительный знак указывает Турбо Ассемблеру, что вы ре-
зервируете ячейку памяти, но не инициализируете ее. Например, в
последнем примере KeyBuffer можно определить так:
KeyBuffer DB 10 DUP (?)
В данной строке резервируется 10 байт памяти, начиная с мет-
ки Keybuffer, но этим байтам не присваивается никакого конкретно-
го значения.
Конечно, каждый раз, когда вы используете неинициализирован-
ную переменную в памяти, вы должны быть уверены в том, что вы
инициализируете ее в своей программе перед тем, как использовать
эту переменную. Например, было бы ошибочным использовать содержи-
мое KeyBuffer в последнем примере до того, как этот массив будет
заполнен, так как находящиеся в KeyBuffer начальные значения не-
определены.
Оставить комментарий
Комментарии
1.


19 апреля 2014, 19:21:23
String1 DB 'Line1','$',0dh,0ah,'$'
mov ah,9 ; функция DOS печати строки
mov dx,OFFSET String1 ; печатаемая строка
int 21h ; вызвать DOS для печати строки
Разве не остановится вывод после первого бакса?
Мне кажется перевод каретки так и не выведется. Все строки выведутся в одну.
Надо сделать так:
String1 DB 'Line1',0dh,0ah,'$'
mov ah,9 ; функция DOS печати строки
mov dx,OFFSET String1 ; печатаемая строка
int 21h ; вызвать DOS для печати строки
Разве не остановится вывод после первого бакса?
Мне кажется перевод каретки так и не выведется. Все строки выведутся в одну.
Надо сделать так:
String1 DB 'Line1',0dh,0ah,'$'

