Использование программно-доступных регистров микропроцессора Intel 8086




В языке Си для IBM-совместимых персональных компьютеров обращение к регистрам микропроцессора Intel 8086 осуществляется с помощью специальных объектов, называемых псевдопеременными. Полный список псевдопеременных включает 21 элемент: _АХ, _ВХ, _СХ, _DX, _CS, _DS, _SS, _ES, _SP, _ВР, _DI, _SI, _AL, _AH, _BL, _ВH, _CL, _СН, _DL, _DH, _FLAGS. Их имена образуются из имен регистров с префиксом _ (например, переменная _AX связана с регистром AX). Первые двенадцать псевдопеременных и последняя имеют тип unsigned int, а оставшиеся восемь - unsigned char. Присвоение значения какой-либо переменной, например _АХ, вызывает занесение этого значения в регистр АХ. Получение значения переменной, например _ВХ, эквивалентно получению значения из регистра ВХ.

 

РАЗДЕЛ 7. ПРИМЕРЫ

Рассмотрим примеры программ, в которых используются различные конструкции языка Си. Первый из них демонстрирует использование управляющих символов n в функциях printf() и scanf().

/* Пример 1 */

#include <stdio.h>

 

void main(void)

{

int x, n1, n2;

 

printf("Введите целое число от -32768 до 32767\n");

scanf("%d%n", &x, &n1);

printf("x = %d%n\n", x, &n2);

printf("n1 = %d, n2 = %d\n", n1, n2);

}

Результаты работы этой программы имеют вид:

Введите целое число от -32768 до 32767

234<Enter>

x = 234

n1 = 3, n2 = 7

Значение n1 определяет число введенных цифр, а n2 - число выведенных символов в строке x = 234 (с пробелами).

Следующий пример показывает использование спецификаций %[], а также символов * и #.

/* Пример 2 */

#include <stdio.h>

 

void main(void)

{

char str_b[21], str_c[21]; /* Последний элемент резервируем под \0 */

int x, n1, n2;

float y;

 

printf("Введите строку до 20 символов\n");

scanf("%[Computer]%s", str_b, str_c);

printf("str_b = %s, str_c = %s\n", str_b, str_c);

y = 12.345678;

n1 = 8;

n2 = 3;

x = 0x100;

printf("y = %*.*f\n", n1, n2, y);

printf("x(16) = %#x, x(16) = %x, x(10) = %i\n", x, x, x);

}

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

Введите строку до 20 символов

Comp-1-2-3-4-5<Enter>

str_b = Comp, str_c = -1-2-3-4-5

у = 12.346

x(16) = 0x100, x(16) = 100, x(10) = 256

Здесь пользователем введена строка Comp-1-2-3-4-5. Из нее только четыре символа (Comp) совпадают с первыми символами, заданными в квадратных скобках рассматриваемой спецификации [Computer]. Поэтому только эти четыре символа попадут в первую строку, а оставшиеся символы (1-2-3-4-5) попадут во вторую строку. Число n1 определяет минимальную ширину поля для вывода, а число n2 = 3 - количество цифр после запятой. В результате число 12.345678 будет смещено относительно левой границы, и после запятой будут выведены три цифры. Шестнадцатеричное число 0х100 выведено функцией printf() с префиксом 0x, без префикса 0x и в десятичной форме.

Третья программа демонстрирует использование условного оператора if...else и оператора for для организации цикла.

/* Пример 3 */

#include <conio.h>

#define SYM 'X' /* Выводимый символ */

#define SPACE ' ' /* Определение пробела */

#define LF 10 /* Перевод строки */

#define CR 13 /* Возврат каретки */

#define LEFT 24 /* Левая граница символа */

#define RIGHT 51 /* Правая граница символа */

#define BOTTOM 25 /* Нижняя граница символа */

 

void main(void)

{

int col, line; /* col - номер колонки для вывода символа */

/* line - номер линям для вывода символа */

clrscr();

for (line = 1; line <= BOTTOM; line++) /* Вывод пробелов до левой

границы символа */

{

for (col = 1; col < LEFT; col++) putch(SPACE);

for(col = LEFT + 1; col < RIGHT; col++) /* Вывод символа X

на весь экран */

if ((col == (LEFT + line)) || (col == (RIGHT - line)))

putch(SYM);

else putch(SPACE);

putch(LF); /* Возврат каретки и перевод строки после */

putch(CR); /* вывода каждой линии символа */

}

getch(); /* Ожидание нажатия клавиши */

}

После ее запуска на весь экран будет выведен символ X.

Новая библиотечная функция clrscr() имеет следующий прототип:

void clrscr (void);

Она выполняет очистку экрана и объявлена в заголовочном файле conio.h.

Четвертая программа демонстрирует использование рекурсивной функции для вычисления факториала. (Отметим, что определение функции factorial() может находиться и после функции main(), но в этом случае функция factorial() должна быть объявлена перед функцией main(), т.е. до main() необходимо поместить строку: long factorial(int);.)

/* Пример 4 */

#include <stdio.h>

#include <values.h>

#include <process.h>

 

long factorial(int value) /* Рекурсивная функция */

{

long result = 1;

 

if (value!= 0)

{

result = factorial(value - 1);

/* Проверка возможности вычисления факториала */

if (result > MAXLONG / (value + 1))

{

fprintf(stderr, "Очень большое число\n");

getch(); /* Ожидание нажатия клавиши */

exit (1);

}

result *= value;

}

return(result);

}

/* Рекурсивное вычисление факториала числа value */

void main(void)

{

int value; /* Факториал этого значения вычисляется */

long result; /* Переменная для результата */

 

puts("Факториал какого числа?");

scanf("%d", &value);

result = factorial(value);

printf("Результат: %ld\n", result);

getch(); /* Ожидание нажатия клавиши */

}

Результаты работы этой программы:

Факториал какого числа? 10<Enter>

Результат: 362880

Пятая программа подсчитывает число символов и слов во вводимых строках (новые символы и слова суммируются с предыдущими; пробелы входят в число введенных символов).

/* Пример 5 */

#include <stdio.h>

#include <conio.h>

#define ESC 27 /* 27 - ASCII-код клавиши ESC */

 

void CountOfLines(void)

{

/* Статические переменные будут сохранять старые значения при каждом

новом вызове функции CountOfLines */

static int words = 0, symbols = 0; /* words-число слов,

symbols-число символов */

char temp, t = 0; /* Временные переменные */

 

++symbols;

/* Число символов и слов выдается после нажатия клавиши <Enter> */

while ((temp = getche())!= '\r')

{

++symbols; /* Подсчитывается каждый символ */

/* После одного или нескольких пробелов подсчитывается слово */

if ((temp == ' ') && (t == 1)) continue;

if (temp == ' ') { t = 1; ++words; }

else t = 0;

}

if (t == 1) --words;

else ++words;

printf ("\n Слов: %d; символов: %d\n", words, symbols);

}

void main(void)

{

puts("Для завершения программы нажмите <ESC> в начале строки");

puts("Строка не должна начинаться с пробела и с нажатия клавиши"

"<Enter>");

puts("Строка не должна завершаться пробелом");

while (getche()!= ESC) CountOfLines();

putch('\b');

putch(' ');

putch('\b');

}

Результаты работы этой программы:

Для завершения программы нажмите <ESC> в начале строки

Строка не должна начинаться с пробела и с нажатия клавиши <Enter>

Строка не должна завершаться пробелом

Mouse Keyboard <Enter>

Слов: 2 символов: 14

<ESC>

Следующая группа программ демонстрирует работу с файлами. Она позволяет организовать в файле на диске телефонный справочник и выполняет следующие функции:

  • занесение фамилии абонента и номера телефона в справочник;
  • поиск в справочнике номера телефона по фамилии абонента;
  • удаление из справочника фамилии абонента и номера его телефона.

Ниже приведен текст головной программы main.c:

// Пример 6

//---------------------------------------------------------

// Головная программа для работы с телефонным справочником

//---------------------------------------------------------

#include "A:\my.h" //Заголовочный файл с глобальными

//переменными и константами

#include "A:\findt.c" //Поиск строки str в файле

#include "A:\choicet.c" //Проверка наличия строки в файле

#include "A:\addt.c" //Добавление строки в файл

#include "A:\subt.c" //Удаление строки из файла

 

void main(int argc, char *argv[ ])

{

if (argc == 3)

if (*argv[1] == '+') //Добавить запись

{

if (Choice(argv[2]) == 0) //Нет ли такой

//записи в файле?

{

puts("Эта фамилия есть в справочнике");

exit(1);

}

Add(argv[2]); //Добавление записи

}

else if (*argv[1] == '-') Sub(argv[2]); //Удалить запись

else puts("Ошибочное значение аргумента");

else if (argc == 2) Find(argv[1]); //Поиск записи

else puts("Ошибочное число аргументов");

}

С помощью директив #include в головную программу включаются файлы: my.h, findt.c, choicet.c, addt.c и subt.c. Считается, что все они находятся в корневом каталоге диска A:. Если это не так, то необходимо изменить соответствующие директивы #include. В файле my.h определены глобальные переменные и некоторые символьные значения.

//Файл заголовков my.h

//--------------------------------------------------------

//Определения глобальных переменных и символьных значений

//--------------------------------------------------------

#include <stdio.h>

#include <process.h>

#include <string.h>

#define MAX_NAME 20 //Максимальное число символов в фамилии

#define MAX_NUMBER 10 //Максимальное число цифр в телеф. номере

char Name[MAX_NAME]; //Массив фамилий

char Number[MAX_NUMBER]; //Массив для телефонного номера

char File[ ] = "A:\\tel\\tel_num.txt"; //Имя файла справочника

int Count; //Число фамилий в справочнике

FILE *F_tel; //Логическое имя файла справочника

Файл my.h, в частности, определяет, что телефонный справочник будет организован в каталоге tel диска A:. Поэтому необходимо перед запуском программы main.exe создать этот подкаталог либо использовать другой подкаталог. В последнем случае необходимо изменить строку:

char File[ ] = "A:\\tel\\tel_num.txt";

которая задает имя файла с телефонным справочником (tel_num.txt).

Модуль findt.c, текст которого приведен ниже, содержит функцию Find() для поиска строки str в файле tel_num.txt.

//Модуль findt.c

//----------------------------------------------------------

//Функция Find() для поиска строки str в файле tel_num.txt

//----------------------------------------------------------

void Find(char *str)

{

int i;

//Если файл невозможно открыть для чтения, то программа

//завершаетработу

if ((F_tel = fopen(File, "r")) == NULL)

{

fprintf(stderr, "\"%s\": невозможно открыть\n", File);

exit(1);

}

//Чтение числа записей (Count) в файле

if (fread(&Count, sizeof(int), 1, F_tel)!= 1)

{

fprintf(stderr, "\"%s\": ошибкачтения\n", File);

exit(1);

}

//В цикле for осуществляется поиск нужной записи

for (i = 1; i < Count; i++)

{

fread(Name, 1, MAX_NAME, F_tel); //Чтениеимени

fread(Number, 1, MAX_NUMBER, F_tel); //Чтениеномера

if (ferror(F_tel)) //Проверка отсутствия ошибки

{

fprintf(stderr, "\"%s\": ошибка чтения\n'', File);

exit(1);

}

if (strcmp(str, Name) == 0) //Если имя совпадает

//с введенным, то фамилия

//и найденный номер

//выводятся на экран

{

printf("Фамилия: %s\n", Name);

printf("Номертелефона: %s\n", Number);

fclose(F_tel);

return;

}

}

//Если результат поиска отрицательный, то выводится

//следующее сообщение

fprintf(stderr,"\"%s\": запись в файле отсутствует\n", File);

fclose(F_tel);

return;

}

Модуль choicet.c содержит функцию Choice(), позволяющую проверить есть ли заданная строка в файле tel_num.txt.

 

// Модуль choicet.c

//----------------------------------------------------------------------

//Функция Choice(), проверяющая есть ли строка str в файле tel_num.txt

//----------------------------------------------------------------------

int Choice(char *str)

{

int i;

char temp[MAX_NAME + MAX_NUMBER];

 

if ((F_tel = fopen(File, "r")) == NULL)

return 1; //Строки str нет в файле

if (fread(&Count, sizeof(int), 1, F_tel)!= 1)

{

fprintf(stderr, "\"%s\": ошибкачтения\n", File);

exit(1);

}

for (i = 0; i < Count; i++)

{

fread(temp, 1, MAX_NAME + MAX_NUMBER, F_tel);

if (ferror(F_tel))

{

fprintf(stderr, "\"%s\": ошибкачтения\n", File);

exit(1);

}

if (strcmp(str, temp) == 0)

{

fclose(F_tel);

return 0; //Строка str есть в файле

}

}

fclose(F_tel);

return 1; //Строки str нет в файле

}

Модуль addt.c содержит функцию Add(), которая добавляет заданную строку в файл tel_num.txt.

//Модуль addt.c

//-------------------------------------------------------

//Функция Add() добавляет строку str в файл tel_num.txt

//-------------------------------------------------------

void Create(void) //Создает файл, если он не существует

{

if ((F_tel = fopen(File, "wb+")) == NULL)

{

fprintf(stderr, "\%s\": невозможнооткрыть\n", File);

exit(1);

}

Count = 0;

if (! fwrite(&Count, sizeof(Count), 1, F_tel))

{

fprintf(stderr, "\"%s\": ошибказаписи\n", File);

exit(1);

}

}

void Add(char *s) //Добавляет запись в файл

{

char str[MAX_NAME], sn[MAX_NUMBER]; //Временныемассивы

int i;

 

for (i = 0; i < MAX_NAME; i++)

str[i] = ' '; //Пробелы в str

strcpy(str, s); //Копирование строки в str

if ((F_tel = fopen(File, "rb+")) = = NULL)

Create(); //Создаем файл, если он не

//существует

else if (fread(&Count, sizeof(Count), 1, F_tel)!= 1)

{

fprintf(stderr, "\"%s\": ошибкачтения\n", File);

exit(1);

}

printf("Номер телефона: "); //Запрашивается и вводится номер

if (gets(Number) == NULL || *Number == '\0')

{

fclose(F_tel);

return; //Возврат, если номер не введен

}

//Установка указателя в файле на первую свободную запись

if (fseek(F_tel, (long)((MAX_NAME+MAX_NUMBER)*Count), SEEK_CUR)!=0)

{

fprintf(stderr, "\"%s\": ошибкапоиска\n", File);

exit(1);

}

fwrite(str, 1, MAX_NAME, F_tel); //Записьвфайлфамилии

for (i = 0; i < MAX_NUMBER; i++)

sn[i] = ' '; //Пробелы в sn[ ]

strcpy(sn, Number); //Копирование сроки Number в строку sn

fwrite(sn, 1, MAX_NUMBER, F_tel); //Запись в файл номера

if (ferror(F_tel)) //Проверка наличия ошибки

{

fprintf(stderr, "\"%s\": ошибказаписи\n", File);

exit(1);

}

//Установка указателя в файле на первый байт

if (fseek(F_tel, 0L, SEEK_SET)!= 0)

{

fprintf(stderr, "\"%s\": ошибкапозиционирования\n", File);

exit(1);

}

++Count; //Увеличение числа записей на единицу

//Запись Count вфайл

if (fwrite(&Count, sizeof(int), 1,F_tel)!= 1)

{

fprintf(stderr, "\"%s\": ошибказаписи\n", File);

exit(1);

}

fclose(F_tel);

return;

}

Модуль subt.c содержит функцию Sub(), которая удаляет заданную строку из файла tel_num.txt.

//Модуль subt.c

//------------------------------------------------------------

//Функция Sub() удаляет заданную строку из файла tel_num.txt

//------------------------------------------------------------

void Sub(char *str)

{

int i, j;

char temp[MAX_NAME + MAX_NUMBER]; //Временныймассив

 

if ((F_tel = fopen(File, "r+")) == NULL)

{

fprintf(stderr, "\"%s\": невозможнооткрыть\n", File);

exit(1);

}

if (fread(&Count, sizeof(int), 1, F_tel)!= 1)

{

fprintf(stderr, "\"%s\": ошибкачтения\n", File);

exit(1);

}

//В цикле осуществляется поиск удаляемой строки в файле

for (i = 0; i < Count; i++)

{

fread(temp, 1, MAX_NAME + MAX_NUMBER, F_tel);

if (ferror(F_tel))

{

fprintf(stderr, "\"%s\": ошибкачтения\n", File);

exit(1);

}

if (strcmp(str, temp) == 0) //Еслисроканайдена

{

for (j = i; j < Count; j++) //онаудаляется

{

fread(temp, 1, MAX_NAME + MAX_NUMBER, F_tel);

fseek(F_tel, (long)(j*(MAX_NAME+MAX_NUMBER)+2L), SEEK_SET);

fwrite(temp, 1, MAX_NAME + MAX_NUMBER, F_tel);

fseek(F_tel, (long)((j+2)*(MAX_NAME+MAX_NUMBER)+2L), SEEK_SET);

if (ferror(F_tel))

{

fprintf(stderr, "\"%s\": ошибкачтения\n", File);

exit(1);

}

}

--Count; //При удалении строки декремент Count

fseek(F_tel, 0L, SEEK_SET); //Установка указателя

//Запись уменьшенного значения Count в файл

if (fwrite(&Count, sizeof(Count), 1, F_tel)!= 1)

{

fprintf(stderr, "\"%s\": ошибказаписи\n", File);

exit(1);

}

fclose(F_tel);

puts("Запись удалена из файла");

return;

}

}

fprintf(stderr, "\"%s\": отсутствует в базе данных\n", File);

fclose(F_tel);

}

Ниже приводится возможный сценарий работы с программой main.

main + Петров<Enter>

Номер телефона: 77-17-89<Enter>

main + Иванов<Enter>

Номер телефона: 52-98-02<Enter>

 

main Иванов<Enter>

Фамилия: Иванов

Номер телефона: 52-98-02

 

main - Петров<Enter>

Запись удалена из файла

 

main Петров<Enter>

"tel_num.txt": запись в файле отсутствует

Последняя программа showt.c позволяет вывести на экран содержимое телефонного справочника.

//Программа showt.c

//-------------------------------------------------

//Выводит на экран все записи из файла tel_num.txt

//-------------------------------------------------

#include "my.h"

void Show(void)

{

int i;

//Если файл невозможно открыть для чтения, то завершение работы программы

if ((F_tel = fopen(File, "r")) == NULL)

{

fprintf(stderr, "\"%s\": невозможнооткрыть\n",File);

exit(1);

}

//Чтение числа записей (Count) в файле

if(fread(&Count, sizeof(int), 1, F_tel)!= 1)

{

fprintf(stderr, "\"%s\": ошибкачтения\n", File);

exit(1);

}

//В цикле осуществляется вывод всех записей

for (i=0; i < Count; i++)

{

fread(Name, 1, MAX_NAME, F_tel); //Читаетсяимя

fread(Number, 1, MAX_NUMBER, F_tel); //Читаетсяномер

if (ferror(F_tel)) //Проверяется отсутствие ошибки

{

fprintf(stderr, "\"%s\": ошибка чтения\n'', File);

exit(1);

}

printf("Фамилия: %s; номертелефона: %s\n", Name, Number);

}

fclose(F_tel);

}

void main(void)

{

Show();

}

 

 

ЛИТЕРАТУРА

  1. Скляров В.А. Программирование на языках Си и Си++.- М.: Высшая школа, 1996.
  2. Березин Б.И., Березин С.Б. Начальный курс С и С++.- М.: ДИАЛОГ-МИФИ, 1999.
  3. Керниган Б., Ритчи Д. Язык программирования Си.- М.: Финансы и статистика, 1992.
  4. Подбельский В.В., Фомин С.С. Программирование на языке Си. Учеб. пособие.- М.: Финансы и статистика, 2000.
  5. Павловская Т.А. C/C++, Программирование на языке высокого уровня.- СПб.: Питер, 2005.
  6. Касаткин А.И. Профессиональное программирование на языке Си. Системное программирование.- Минск: Высшая школа, 1993.
  7. Касаткин А.И. Профессиональное программирование на языке Си. Управление ресурсами.- Минск: Высшая школа, 1993.
  8. Касаткин А.И., Вальвачев А.Н. Профессиональное программирование на языке Си. От Turbo C к Borland C++.- Минск: Высшая школа, 1995.

(c) Курсков С.Ю., составление, 2006-2012

 



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2022-10-12 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: