Главная / Ассемблер / Примеры (исходники) /

Как узнать состояние флага


Лучшие книги по Ассемблеру Лучшие книги по Ассемблеру

Сделал подборку не новых, но проверенных книг по программированию на языке ассемблера. Если вы также как и я любите погружаться на низкий уровень, в те закоулки мира программирования, куда не всем путь открыт, то посмотрите. Возможно, что-то вам понравится. Подробнее...

Как-то один из подписчиков моего канала на Ютуб спросил о том, как можно узнать состояние бита в регистре флагов, то есть состояние отдельного флага. Поскольку ответить на этот вопрос в полной мере в комментариях довольно сложно, я решил посвятить этому отдельную статью.

Вообще это требуется редко. Обычно флаги проверяются после выполнения таких команд, как CMP, инструкциями перехода, такими, например, как JB.

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

Но в наборе команд процессора Intel таких инструкций нет, поэтому, если вам очень захотелось узнать состояние отдельного флага, то придётся подойти к решению этой задачи творчески…

Итак, в языках Ассемблера INTEL есть по крайней мере три способа получить состояние отдельного флага. Далее мы их рассмотрим.

Использование команд перехода

Этот способ вы наверняка уже использовали, сами того не подозревая. Суть его проста - почти все команды условного перехода проверяют какие-то флаги. Соответственно, с их помощью можно узнать состояние этих флагов. Правда, некоторые команды перехода проверяют не один, а несколько флагов. Такие команды для нас не подойдут. А вот те, которые проверяют только один флаг - это то, что нам нужно. Вот они:

Таблица 1. Команды, которые можно использовать для проверки флагов.

Команда Условие перехода
JZ, JE ZF = 1
JC, JB, JNAE CF = 1
JS SF = 1
JO OF = 1
JPE, JP PF = 1
JNZ, JNE ZF = 0
JNC, JNB, JAE CF = 0
JNS SF = 0
JNO OF = 0
JPO, JNP PF = 0

Как видно из таблицы, с помощью команд перехода можно проверить почти все основные флаги.

А теперь о том, как это использовать. Поясню на примере:

.model tiny
.code
ORG    100h
	
start:	
  MOV AH, 7
  CMP AH, 7    ;ZF = 1
  JZ  ZF_1
  JMP ZF_0
	
ZF_1:          ;Если ZF = 1, то 
  MOV AH, 1    ;в AH запишем 1
ZF_0:          ;Если ZF = 0, то 
  MOV AH, 0    ;в AH запишем 0
  
  RET

END	start

Если флаг ZF = 1, то мы переходим к метке ZF_1 и записываем в регистр АН число 1. Если флаг ZF = 0, то мы переходим к метке ZF_0 и записываем в регистр АН число 0. Таким образом мы узнаём состояние флага ZF и записываем его в регистр AH.

Чтение флагов в регистр

Имеется также особая команда, которая позволяет загрузить младшие 8 битов регистра флагов в регистр AH. Это команда LAHF. Пример:

.model tiny
.code
ORG    100h
	
start:	

  LAHF        ;AH = 02h = 00000010 (ZF = 0)
  MOV BH, 7
  CMP BH, 7
  LAHF        ;AH = 46h = 01000110 (ZF = 1, PF = 1)

  RET

  END	start

Команда LAHF загружает в регистр АН следующие флаги:

Разряды регистра АН и флаги, которые в них загружает команда LAHF
7 6 5 4 3 2 1 0
SF ZF 0 AF 0 PF 1 CF

То есть в разряд 1 всегда загружается единица (поэтому в примере выше первый вызов LAHF загрузил в АН число 2), в разряды 3 и 5 всегда загружается 0. В остальные разряды загружаются состояния соответствующих флагов на момент вызова команды LAHF.

Чтение флагов через стек

Есть также команда PUSHF, которая загружает регистр флагов в стек. Преимущество этой команды в том, что она загружает все флаги (даже если регистр флагов 32-разрядный). Однако её не советуют использовать без крайней необходимости, потому что она выполняется довольно медленно (иногда это важно).

Ещё одно удобство этой команды заключается в том, что она загружает именно регистр флагов. И если потом выгрузить стек, например, в регистр АХ, то все биты регистра АХ будут установлены в том же порядке, что и биты регистра флагов. Пример:

.model tiny
.code
ORG    100h
	
start:	

  PUSHF    ;Получить регистр флагов в стек
  POP AX   ;Выгрузить из стека а АХ (АХ = 0202h)
  STC      ;Установить флаг CF
  PUSHF    ;Получить регистр флагов в стек
  POP AX   ;Выгрузить из стека а АХ (АХ = 0203h)  

  RET

  END	start

Команда STC устанавливает флаг CF. Но об этом как-нибудь в другой раз...



Инфо-МАСТЕР ®
Все права защищены ©
e-mail: mail@info-master.su