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,'$'