- •Аппаратно-ориентированное программирование
- •Ббк 32.973.73
- •Удк 681.3 ббк 32.973.73ф 73
- •1. Основы программирования на ассемблере
- •1.1. Принципы построения ассемблерных программ
- •1.2. Понятие архитектуры компьютера
- •1.3. Регистры программиста в ia32
- •1.4. Описание сегментной структуры программы
- •2. Простейшие средства ассемблера
- •2.1. Средства описания данных
- •2.2. Обращения к функциям ос посредством прерываний
- •2.3. Средства преобразования в исполняемый файл
- •2.4. Управление строками при выводе и ввод данных
- •2.5. Простейшие способы адресации
- •3. Архитектурные элементы для построения программ
- •3.1. Организация условных переходов
- •3.2. Средства организации циклов
- •3.3. Особенности команд умножения и деления
- •3.4. Организация процедур
- •3.5. Неарифметические операции над кодами
- •4. Использование неэлементарных способов адресации
- •4.1. Косвенно-регистровая адресация
- •4.2. Использование индексной адресации данных
- •4.3. Базовая и индексно базовая адресации
- •4.4. Адресация с масштабированием
- •5. Взаимосвязи программных единиц
- •5.1. Многомодульная разработка программ
- •5.2. Использование библиотек объектных модулей
- •5.3. Организация стекового кадра подпрограммы
- •5.4. Программный доступ к системным функциям Win32
- •5.5. Особенности использования объектных файлов формата coff
- •5.6. Стандартный доступ к системным функциям Unix
- •6. Вспомогательные средства базовой архитектуры
- •6.1. Использование строковых команд пересылки
- •6.2. Применение строковых команд сравнения
- •7. Использование ассемблерных отладчиков
- •7.1. Особенности отладчика gdb для программ в Linux
- •7.2. Отладчики текстового режима для Windows
- •Библиографический список
- •Оглавление
2.4. Управление строками при выводе и ввод данных
При выполнении программ, приведенных исходными текстами в листингах 2.2.1, 2.3.1 и 2.3.2, текст из внутренней области txt и далее выводимый символ из внутренней области symbl сливаются в общий текст. Более того, в Linux последующий ввод приглашения для дальнейшей работы также сливается с введенным текстом без перехода на новую строку. Даже в таких простейших примерах происходящее не очень удобно. Поэтому в любой из операционных систем, ориентированных на диалоговое взаимодействие с пользователем, присутствуют простые средства управления выводом на экран. Этими средствами являются управляющие символы, которые на языке Си изображаются внутри текста специальными символьными комбинациями '\n' и '\r'. В рассматриваемых ассемблерах такие символьные комбинации не используются (но используются в специализированном ассемблере AT&T, вызываемом командой as ОС Unix). Вместо управляющих символьных комбинаций следует использовать числовые значения управляющих символов. Ими являются, соответственно, числа 10 и 13. Причем для перевода на новую строку с автоматическим переходом в ее начала для Unix достаточно использовать единственный управляющий символ со значением 10, а в MS-DOS указанные управляющие символы действуют независимо друг от друга.
Для ввода данных из файлов в Unix и MS-DOS предназначена системная функция, задаваемая следующим прототипом на языке Си:
unsigned int read(int handle, char *buffer, unsigned int size).
Число действительно введенных байтов эта функция возвращает в качестве собственного значения. Это число включает не только явно видимые символы, но и завершающий символ перевода строки '\n', образуемый при вводе с клавиатуры нажатием клавиши Enter. Например, число, возвращаемое функцией read после ввода с клавиатуры текста Privet, будет равно 7 (а вовсе не шести, как можно было бы подумать).
При реализации функций, возвращающих значения, на системном уровне принято, что такие значения при возможности возвращаются в регистре eax или, если используемая ОС 16-битная, то в регистре ax. Естественно, что это соглашение используется и для собственно системных функций.
Последняя информация дает нам возможность составить программу, которая использует ввод данных с клавиатуры. Для этого достаточно использовать хэндл стандартного ввода, имеющий в Unix и MS-DOS константное значение, равное нулю. На листинге 2.4.1 приведена программа для Linux,
GLOBAL _start
SEGMENT .text
_start:
;--- read(0, buf, 20) == <3>(ebx, ecx, edx)
mov eax,3 ; N function=write
mov ebx,0 ; N handle=1 (stdout)
mov ecx, buf ; address of txt
mov edx,20 ; number of byte
int 80h
add eax, 9 ; ; sum length of txt + actual read
mov edx, eax
;--- write(1, txt, len) == <4>(ebx, ecx, edx)
mov eax,4 ; N function=write
mov ebx,1 ; N handle=1 (stdout)
mov ecx, txt ; address of txt
int 80h
mov eax,1 ; N function=exit
int 80h
SEGMENT .data
txt db 'Vvedeno: '
buf times 20 db 0
Листинг 2.4.1. Использование элементарных ввода и вывода в Linux
которая после запуска ожидает ввода текста (не более чем двадцати символов) и после этого отображает введенный текст с предшествующим ему текстовым примечанием, взятым из области данных с именем txt. Полученное в регистре eax число введенных символов складывается с известным числом символов в области txt, а результат переносится в регистр edx, который в ближайшем обращении к функции вывода должен содержать число выводимых символов. Заметим, что в число символов, выводимых программой, входит и управляющий символ перевода строки, помещенный в буфер buf системной функцией read и учитываемый возвращаемым значением в регистре eax.
Сложение выполняется с помощью команды ADD, которая по своему назначению складывает число, заданное вторым операндом, со значением, заданным в первом операнде. Практически действие этой команды аналогично действиям оператора += из языка Си, и результат сложения размещается в месте, указанном первым операндом.
Заметим, что в качестве второго операнда этой команды можно использовать как регистр или имя места в области данных, так и числовое значение, но первый операнд может быть задан либо регистром, либо обозначением места в памяти (а числовую константу на этом месте записать нельзя).
На листинге 2.4.2 приведена программа, которая делает то же самое, но предназначена для MS-DOS.
SEGMENT .text
org 100h
start:
;--- read(0, buf, 20) == <3fh>(bx, dx, cx)
mov ah,3fh ; N function=write
mov bx,0 ; N handle=1 (stdout)
mov cx,20 ; number of byte
mov dx, buf ; address of text
int 21h
add ax, 9 ; sum length of txt + actual read
mov cx, ax
;--- write(1, txt, len) == <40h>(bx, dx, cx)
mov ah,40h ; N function=write
mov bx,1 ; N handle=1 (stdout)
mov dx, txt ; address of text
int 21h
int 20h ; function=exit for COM-file
;;--- SEGMENT .data
txt db 'Vvedeno: '
buf TIMES 20 db 0
Листинг 2.4.2. Использование элементарных ввода и вывода в MS-DOS