Лекция Соболевой
Вид материала | Лекция |
- Лекция Соболевой, 659.2kb.
- Элективный курс по правоведению для 9 класса «Символика Российского государства», 86.61kb.
- «Социальная стратификация и социальная мобильность», 46.19kb.
- Программа по русскому языку по системе Л. В. Занкова. Урок обучения грамоте. Знакомство, 19.7kb.
- Первая лекция. Введение 6 Вторая лекция, 30.95kb.
- Лекция Сионизм в оценке Торы Лекция Государство Израиль испытание на прочность, 2876.59kb.
- Текст лекций н. О. Воскресенская Оглавление Лекция 1: Введение в дисциплину. Предмет, 1185.25kb.
- Собрание 8-511 13. 20 Лекция 2ч режимы работы эл оборудования Пушков ап 8-511 (ррэо), 73.36kb.
- Концепция тренажера уровня установки. Требования к тренажеру (лекция 3, стр. 2-5), 34.9kb.
- Лекция по физической культуре (15. 02.; 22. 02; 01. 03), Лекция по современным технологиям, 31.38kb.
Чтение файла при помощи fgetc. Функция fgetc применяется для чтения символа из потока.int fgetc(FILE *fp); В случае успеха, fgetc возвращает следующий байт или символ из потока (зависит от того, файл "двоичный" или "текстовый"). В противном случае, fgetc возвращает ссылка скрыта. (Отдельный тип ошибок можно определить вызовом ferror или feof с указателем на файл.) Чтение файла при помощи fgetsФункция fgets применяется для чтения строки из потока. Считывание происходит до тех пор пока не будет достигнут конец строки (ссылка скрыта:0D0A, эквивалентны в ссылка скрыта \n) или длина строки n, в которую происходит считывание. char *fgets(char *string, int n, FILE *fp); Функция fgets возвращает указатель на строку string. В случае ошибки или конца файла возвращается значение NULL. Для определения того, что произошло - ошибка или конец файла, используются функции ссылка скрыта и ferror. Чтение файла при помощи fread int fread (char *buffer, int size, int count, FILE *fp); Данная функция читает объекты размера size по счетчику count из входного потока fp и располагает их в буфере buffer. fread возвращает число действительно прочитанных объектов, которое меньше, чем count, если при чтении возникла ошибка или встретился конец файла. Запись в файл при помощи fwritefwrite определяется как int fwrite ( const char * array, size_t size, size_t count, FILE * stream ); Функция fwrite записывает блок данных в поток. Таким образом запишется ссылка скрыта элементов count в текущую позицию в потоке. Для каждого элемента запишется size байт. Индикатор позиции в потоке изменится на число байт, записанных успешно. Возвращаемое значение будет равно count в случае успешного завершения записи. В случае ошибки возвращаемое значение будет меньше count. Запись в поток при помощи fputc Функция fputc применяется для записи символа в поток. int fputc(int c, FILE *fp); Параметр c "тихо" конвертируется в unsigned char перед выводом. Если прошло успешно, то fputc возвращает записанный символ. Если ошибка, то fputc возвращает EOF. Запись в поток при помощи fputs int fputs (char *string, FILE *fp); Функция fputs копирует строку в конец потока fp. Нулевой символ окончания '\0' не копируется. Возвращает последний записанный символ. Если вводимая строка string пустая, возвращается значение 0. Значение EOF свидетельствует об ошибке. Форматный ввод из файла fscanf int fscanf(FILE *fp, char *format[,arguments]); Возвращает количество успешно проведенных преобразований. Процесс заканчивается при встрече первой неподходящей литеры или признака конца файла (EOF). Ноль на выходе означает, что не обработано ни одного поля. (format описан ниже =>) fscanf("%i %i",&x1,&x2); Форматный вывод в файл fprintf int fprintf(FILE *fp, char *format[,arguments]); Функция fprintf форматирует и печатает в выходной поток наборы символов и значений. Каждый аргумент (если он есть) преобразуется и выводится согласно заданной спецификации формата в строке формата. Строка формата (format) обладает той же формой и функцией, что и аргумент строки формата функции printf. fprintf("Вывод = %d,%f\n",i,r); => Элемент формата(format) представляет собой последовательность : % [ - ] [ длина поля ] [ . точность ] [ l ] спецификация типа “ - “ означает сдвиг выводимых данных к левому краю поля ( по умолчанию данные сдвигаются вправо); длина поля - количество позиций для вывода; точность - количество дробных цифр для чисел или количество выводимых символов строки для строк; “ . ” - разделитель; l - означает, что число должно рассматриваться как long или double. Могут использоваться следующие спецификации типов : d,i - для данных типа int; u - для данных типа unsigned; o - для данных типа unsigned (выводятся в восьмеричном виде); x,X - для данных типа unsigned (выводятся в шестнадцатеричном виде), шестнадцатеричные цифры A,B,C,D,E,F изображаются большими буквами при использовании типа X и малыми буквами при использовании x; c - для данных типа char, unsigned char (выводятся в символьном виде); f - для данных типа float,double (выводятся в виде с фиксированной точкой, по умолчанию выводится 6 дробных цифр); e,E - для данных типа float,double (выводятся в виде с плавающей точкой, по умолчанию выводится 7 цифр мантиссы и две цифры порядка, всего 13 позиций), отличаются изображением буквы E; g,G - для данных типа float,double - величины 0.0001<|x|<1000000 выводятся в виде с фиксированной точкой с шестью значащими цифрами, другие величины выводятся с плавающей точкой с шестью значащими цифрами (всего занимают 12 позиций), спецификации g и G различаются только изображением буквы e(E); s - для строк; p - для данных типа указатель. Перед выводом всегда осуществляется преобразование данных к типу, определенному спецификацией, что может приводить к изменению выводимого значения. Программист сам должен заботиться о правильном выборе формата, поскольку компилятор не обращает на это никакого внимания. Несоответствие количества элементов формата и количества выводимых данных также может приводить к неприятным последствиям. Пример: #include int main (){ FILE *file; char *fname = "file.txt"; file = fopen(fname,"r"); if(file == 0){ //проверка на успешное открытие файла printf("не могу открыть файл '%s'",fname); return 0; } char ch; while((ch = fgetc(file))!=EOF) //читать пока не конец файла fputc(ch, stdout); //вывод на экран(stdout-поток стандартного вывода, в нашем случае окно консоли) fclose(file); return 0; } 1.12. Микропроцессор Intel х86. Регистры. Команды обмена данными. Команды работы со стеком. Регистры. Регистры общего назначения 32-битные регистры EAX (аккумулятор), EBX (база), ECX (счетчик), EDX (регистр данных) могут использоваться без ограничений для любых целей — временного хранения данных, аргументов или результатов различных операций. Названия этих регистров происходят от того, что некоторые команды применяют их специальным образом: так, аккумулятор часто используется для хранения результата действий, выполняемых над двумя операндами, регистр данных в этих случаях получает старшую часть результата, если он не умещается в аккумулятор, регистр-счетчик используется как счетчик в циклах и строковых операциях, а регистр-база используется при так называемой адресации по базе. Младшие 16 бит каждого из этих регистров могут использоваться как самостоятельные регистры и имеют имена (соответственно AX, BX, CX, DX). Кроме этого, отдельные байты в 16-битных регистрах AX – DX тоже имеют свои имена и могут использоваться как 8-битные регистры. Старшие байты этих регистров называются AH, BH, CH, DH, а младшие — AL, BL, CL, DL (рис. 3). Другие четыре регистра общего назначения — ESI (индекс источника), EDI (индекс приемника), EBP (указатель базы), ESP (указатель стека) — имеют более конкретное назначение и могут применяться для хранения всевозможных временных переменных, только когда они не используются по назначению. Регистры ESI и EDI используются в строковых операциях, EBP и ESP используются при работе со стеком. Так же, как и с регистрами EAX – EDX, младшие половины этих четырех регистров называются SI, DI, BP и SP соответственно. Регистры специального назначения При использовании каждой из сегментированных моделей памяти для формирования любого адреса применяются два числа — адрес начала сегмента и смещение искомого байта относительно этого начала (в бессегментной модели памяти flat адреса начал всех сегментов равны). Операционные системы (кроме DOS) могут размещать сегменты, с которыми работает программа пользователя, в разных местах в памяти, и даже могут временно записывать их на диск, если памяти не хватает. Так как сегменты могут оказаться где угодно, программа обращается к ним, используя вместо настоящего адреса начала сегмента 16-битное число, называемое селектором. В процессорах Intel предусмотрено шесть шестнадцатибитных регистров — CS, DS, ES, FS, GS, SS, используемых для хранения селекторов. Это не значит, что программа не может одновременно работать с большим количеством сегментов памяти, — в любой момент времени можно изменить значения, записанные в этих регистрах. В отличие от регистров DS, ES, GS, FS, которые называются регистрами сегментов данных, регистры CS и SS отвечают за сегменты двух особенных типов — сегмент кода и сегмент стека. Сегмент кода содержит программу, исполняющуюся в данный момент, так что запись нового селектора в этот регистр приводит к тому, что далее будет исполнена не следующая по тексту программы команда, а команда из кода, находящегося в другом сегменте, с тем же смещением. Смещение следующей выполняемой команды всегда хранится в специальном регистре — EIP (указатель инструкции, шестнадцатибитная форма IP), запись в который также приведет к тому, что следующей будет исполнена какая-нибудь другая команда. На самом деле все команды передачи управления — перехода, условного перехода, цикла, вызова подпрограммы и т.п. — и осуществляют эту самую запись в CS и EIP. Команды обмена данными
Базовая команда пересылки данных. Копирует содержимое источника в приемник, источник не изменяется. Команда MOV действует аналогично операторам присваивания из языков высокого уровня, то есть команда mov ax,bx эквивалентна выражению ах := bх; языка Паскаль или ах = bх; языка С, за исключением того, что команда ассемблера позволяет работать не только с переменными в памяти, но и со всеми регистрами процессора. В качестве источника для MOV могут использоваться: число (непосредственный операнд), регистр общего назначения, сегментный регистр или переменная (то есть операнд, находящийся в памяти). В качестве приемника — регистр общего назначения, сегментный регистр (кроме CS) или переменная. Оба операнда должны быть одного и того же размера — байт, слово или двойное слово. Нельзя выполнять пересылку данных с помощью MOV из одной переменной в другую, из одного сегментного регистра в другой и нельзя помещать в сегментный регистр непосредственный операнд — эти операции выполняют двумя командами MOV (из сегментного регистра в обычный и уже из него в другой сегментный) или парой команд PUSH/POP.
Это набор команд, которые копируют содержимое источника в приемник, если удовлетворяется то или иное условие (см. табл. 5). Источником может быть регистр общего назначения или переменная, а приемником — только регистр. Условие, которое должно удовлетворяться, — просто равенство нулю или единице тех или иных флагов из регистра FLAGS, но, если использовать команды CMOVcc сразу после команды СМР (сравнение) с теми же операндами, условия приобретают особый смысл, например: cmp ах,bх ; сравнить ах и bх cmovl ax,bx ; если ах < bх, скопировать bх в ах Слова «выше» и «ниже» в таблице 5 относятся к сравнению чисел без знака, слова «больше» и «меньше» учитывают знак. Таблица 5. Разновидности команды CMOVcc
Содержимое операнда 2 копируется в операнд 1, а старое содержимое операнда 1 — в операнд 2. XCHG можно выполнять над двумя регистрами или над регистром и переменной. xchg eax,ebx ; то же, что три команды на языке С: ; temp = eax; eax = ebx; ebx = temp; xchg al,al ; а эта команда не делает ничего
Обращает порядок байт в 32-битном регистре. Биты 0 – 7 (младший байт младшего слова) меняются местами с битами 24 – 31 (старший байт старшего слова), а биты 8 – 15 (старший байт младшего слова) меняются местами с битами 16 – 23 (младший байт старшего слова). mov eax,12345678h bswap eax ; теперь в еах находится 78563412h Чтобы обратить порядок байт в 16-битном регистре, следует использовать команду XCHG: xchg al,ah ; обратить порядок байт в АХ
Копирует число из порта ввода-вывода, номер которого указан в источнике, в приемник. Приемником может быть только AL, АХ или ЕАХ. Источник — или непосредственный операнд, или DX, причем можно указывать только номера портов не больше 255.
Копирует число из источника (AL, АХ или ЕАХ) в порт ввода-вывода, номер которого указан в приемнике. Приемник может быть либо непосредственным номером порта, либо регистром DX. На командах IN и OUT строится все общение процессора с устройствами ввода-вывода — клавиатурой, жесткими дисками, различными контроллерами, и используются они, в первую очередь, в драйверах устройств. Например, чтобы включить динамик PC, достаточно выполнить команды: in al,61h or al,3 out 61h,al
Команда CWD превращает слово в AХ в двойное слово, младшая половина которого (биты 0 – 15) остается в АХ, а старшая (биты 16 – 31) располагается в DX. Команда CDQ выполняет аналогичное действие по отношению к двойному слову в ЕАХ, расширяя его до учетверенного слова в EDX:EAX. Эти команды всего лишь устанавливают все биты регистра DX или EDX в значение, равное значению старшего бита регистра АХ или ЕАХ, сохраняя таким образом его знак.
CBW расширяет байт, находящийся в регистре AL, до слова в АХ, CWDE расширяет слово в АХ до двойного слова в ЕАХ. CWDE и CWD отличаются тем, что CWDE располагает свой результат в ЕАХ, в то время как CWD, команда, выполняющая точно такое же действие, располагает результат в паре регистров DX:AX. Так же как и команды CWD/CDQ, расширение выполняется путем установки каждого бита старшей половины результата равным старшему биту исходного байта или слова, то есть: mov al,0F5h ; AL = 0F5h = 245 = -11 cbw ; теперь АХ = 0FFF5h = 65 525 = -11
Копирует содержимое источника (регистр или переменная размером в байт или слово) в приемник (16- или 32-битный регистр) и расширяет знак аналогично командам CBW/CWDE.
Копирует содержимое источника (регистр или переменная размером в байт или слово) в приемник (16- или 32-битный регистр) и расширяет нулями, то есть команда movzx ax,bl эквивалентна паре команд mov al,bl mov ah,0
Помещает в AL байт из таблицы в памяти по адресу ES:BX (или ES:EBX) со смещением относительно начала таблицы, равным AL. В качестве аргумента для XLAT в ассемблере можно указать имя таблицы, но эта информация никак не используется процессором и служит только как комментарий. Если этот комментарий не нужен, можно применить форму записи XLATB. В качестве примера использования XLAT можно написать следующий вариант преобразования шестнадцатеричного числа в ASCII-код соответствующего ему символа: mov al,0Ch mov bx, offset htable xlatb если в сегменте данных, на который указывает регистр ES, было записано htable db "0123456789ABCDEF" то теперь AL содержит не число 0Сh, а ASCII-код буквы «С».
Вычисляет эффективный адрес источника (переменная) и помещает его в приемник (регистр). С помощью LEA можно вычислить адрес переменной, которая описана сложным методом адресации, например по базе с индексированием. Если адрес 32-битный, а регистр-приемник 16-битный, старшая половина вычисленного адреса теряется, если наоборот, приемник 32-битный, а адресация 16-битная, то вычисленное смещение дополняется нулями. Команду LEA часто используют для быстрых арифметических вычислений, например умножения: lea bx,[ebx+ebx*4] ; ВХ=ЕВХ*5 или сложения: lea ebx,[eax+12] ; ЕВХ=ЕАХ+12
Помещает содержимое источника в стек. Источником может быть регистр, сегментный регистр, непосредственный операнд или переменная. Фактически эта команда копирует содержимое источника в память по адресу SS:[ESP] и уменьшает ESP на размер источника в байтах (2 или 4). Команда PUSH практически всегда используется в паре с POP (считать данные из стека). Так, например, чтобы скопировать содержимое одного сегментного регистра в другой (что нельзя выполнить одной командой MOV), можно использовать такую последовательность команд: push cs pop ds ; теперь DS указывает на тот же сегмент, что и CS Другое частое применение команд PUSH/POP — временное хранение переменных, например: push eax ; сохраняет текущее значение ЕАХ ... ; здесь располагаются какие-нибудь команды, ; которые используют ЕАХ, например CMPXCHG pop eax ; восстанавливает старое значение ЕАХ
Помещает в приемник слово или двойное слово, находящееся в вершине стека, увеличивая ESP на 2 или 4 соответственно. POP выполняет действие, полностью обратное PUSH. Приемником может быть регистр общего назначения, сегментный регистр, кроме CS (чтобы загрузить CS из стека, надо воспользоваться командой RET), или переменная. Если в роли приемника выступает операнд, использующий ESP для косвенной адресации, команда POP вычисляет адрес операнда уже после того, как она увеличивает ESP.
PUSHA помещает в стек регистры в следующем порядке: АХ, СХ, DX, ВХ, SP, ВР, SI и DI. PUSHAD помещает в стек ЕАХ, ЕСХ, EDX, ЕВХ, ESP, EBP, ESI и EDI. (В случае SP и ESP используется значение, которое находилось в этом регистре до начала работы команды.) В паре с командами POPA/POPAD, считывающими эти же регистры из стека в обратном порядке.
Эти команды выполняют действия, полностью обратные действиям PUSHA и PUSHAD, за исключением того, что помещенное в стек значение SP или ESP игнорируется. РОРА загружает из стека DI, SI, BP, увеличивает SP на два, загружает ВХ, DX, CX, AX, a POPAD загружает EDI, ESI, ЕВР, увеличивает ESP на 4 и загружает ЕВХ, EDX, ЕСХ, ЕАХ. 1.13 Микропроцессор Intel х86. Арифметические команды. Логические команды и команды сдвига. Команды передачи управления. Арифметические команды. 1000000> |