Учебный курс. Часть 24. Команды управления флагами

Автор: xrnd | Рубрика: Учебный курс | 10-09-2010 | Распечатать запись Распечатать запись

В предыдущей части учебного курса мы использовали флаг CF, чтобы вернуть из процедуры информацию об ошибке. Чтобы у вас сложилась полная картина, я решил в этой части подробнее рассказать о командах управления флагами.

Как вы, наверно, помните флаги изменяются в результате выполнения арифметических и логических команд, а также команд сдвига. Регистр флагов можно сохранить в стек с помощью команды PUSHF и восстановить из стека с помощью команды POPF. Кроме того, в процессоре существуют специальные команды, которые позволяют явно установить или сбросить флаги CF, DF и IF. Это очень простые команды: у них нет операндов и результатом является только изменение значения соответствующего флага.

Флаг переноса CF

Команда CLC сбрасывает флаг CF.

Команда STC устанавливает флаг CF в единицу.

Команда CMC инвертирует значение флага CF.

Флаг направления DF

Этот флаг определяет направление обработки данных цепочечными командами (о них подробно расскажу в отдельной статье). Он должен устанавливаться или сбрасываться перед использованием этих команд.

Команда CLD сбрасывает флаг DF.

Команда STD устанавливает флаг DF в единицу.

Флаг прерывания IF

Этот флаг определяет, разрешены в данный момент прерывания или нет (о прерываниях тоже будет отдельная статья).

Команда CLI сбрасывает флаг IF (запрещает прерывания).

Команда STI устанавливает флаг IF в единицу (разрешает прерывания).

Команды LAHF и SAHF

Команда LAHF загружает младший байт регистра флагов в AH. Её удобно использовать, когда нужно получить значения сразу нескольких флагов. Порядок расположения флагов представлен на рисунке:

Команда SAHF выполняет обратную операцию — загружает содержимое AH в младший байт регистра флагов. Это позволяет одновременно изменить значения нескольких флагов. При этом биты 1, 3, 5 регистра AH игнорируются.

Пример программы

В качестве примера использования команды LAHF я написал процедуру, которая получает и выводит на консоль значения флагов SF, ZF, AF, PF и CF. Подобную процедуру можно использовать в отладочных целях. Достаточно добавить её вызов в то место программы, где хочется проверить состояние флагов.

Чтобы выводить значения отдельных битов удобно написать отдельную процедурку для печати флага CF в виде символа. Нужный бит будет помещаться в флаг CF при помощи команды сдвига SHL.

;Процедура вывода значения флага CF в виде символа
print_cf:
    push ax
    push dx
    mov ah,2                ;Функция DOS 02h - вывод символа
    mov dl,'0'              ;DL = '0'
    adc dl,0                ;Если CF = 1, то в DL будет символ '1'
    int 21h                 ;Обращение к функции DOS
    pop dx
    pop ax
    ret

А вот собственно процедура вывода флагов. Как видите, здесь нет ничего сложного :) Процедура сохраняет регистр флагов и восстанавливает его перед возвратом управления, поэтому можно вызывать её где угодно, не волнуясь, что она нарушит выполнение основной программы.

;Процедура вывода состояния флагов на консоль
print_flags:
    push ax
    push cx
    push dx
    pushf                   ;Сохранение регистра флагов
    lahf                    ;Загрузка младшего байта FLAGS в AH
    mov cl,ah               ;CL = AH
    mov ah,9                ;Функция DOS 09h - вывод строки
    mov dx,s_sf             ;DX = адрес строки 'FLAGS: SF='
    int 21h                 ;Обращение к функции DOS
    shl cl,1                ;Сдвиг CL влево на 1 бит
    call print_cf           ;Печать выдвинутого бита
    mov dx,s_zf
    int 21h                 ;Вывод строки ' ZF='
    shl cl,1                ;Сдвиг CL влево на 1 бит
    call print_cf           ;Печать выдвинутого бита
    mov dx,s_af
    int 21h                 ;Вывод строки ' AF='
    shl cl,2                ;Сдвиг CL влево на 2 бита
    call print_cf           ;Печать выдвинутого бита
    mov dx,s_pf
    int 21h                 ;Вывод строки ' PF='
    shl cl,2                ;Сдвиг CL влево на 2 бита
    call print_cf           ;Печать выдвинутого бита
    mov dx,s_cf
    int 21h                 ;Вывод строки ' CF='
    shl cl,2                ;Сдвиг CL влево на 2 бита
    call print_cf           ;Печать выдвинутого бита
    mov dx,s_endl
    int 21h                 ;Вывод конца строки
    popf                    ;Восстановление регистра флагов
    pop dx
    pop cx
    pop ax
    ret

Полный исходный код примера — printflags.asm. Вывод программы выглядит так:

Упражнение

Чтобы потренироваться в работе с флагами напишите следующую программу. Вычислите сумму значений флагов CF, SF, ZF и выведите на консоль результат сложения. Если результат больше 1, инвертируйте значение флага CF :)

Следующая часть »

Комментарии:

Ваш комментарий