X86 플래그 레지스터를 직접 읽고 쓰는 방법은 무엇입니까?
문제
내가 읽은 바에 따르면 9 개의 다른 깃발이있는 것 같습니다. 직접 읽거나 변경할 수 있습니까? 예를 들어 CMP/JMP 명령을 수행 한 후 제로 플래그가 설정되어 있는지 알 수 있지만 다음과 같은 작업을 수행 할 수 있는지 묻습니다.
mov eax, flags
또는 뭔가.
또한 글쓰기를 위해 손으로 설정할 수 있습니까?
해결책
일부 플래그는 특정 지침으로 직접 설정하거나 지울 수 있습니다.
- CLC, STC, 그리고 CMC: 캐리 플래그를 정리하고 설정하고 보완합니다.
- 클리 그리고 스티: 인터럽트 플래그를 지우고 설정하십시오 (원자 적으로 수행해야 함)
- CLD 그리고 std: 방향 플래그를 지우고 설정합니다
기호, 제로, 보조 캐리, 패리티 및 캐리 깃발을 읽고 쓰기 위해 LAHF AH 레지스터에 8 비트 (5 개의 플래그와 3 개의 불확실한 비트)를로드하려면 사용할 수 있습니다. SAHF AH에서 해당 값을 다시 플래그 레지스터에 저장하려면.
당신은 또한 사용할 수 있습니다 푸시프 깃발을 스택에 밀고 스택에서 읽고 수정 한 다음 사용한 다음 사용합니다. POPF1 깃발 레지스터에 다시 저장하도록 지시하십시오.
POPF로 VM 및 RF 플래그를 설정할 수 없습니다. 이전 값을 유지합니다. 마찬가지로, 권한 레벨 0에서 실행할 때만 I/O 권한 레벨 만 변경할 수 있으며, I/O 권한 레벨만큼 권한이있는 권한 수준에서 실행할 때만 인터럽트 플래그를 변경할 수 있습니다.
각주 1 :
주목하십시오 popf
현대 CPU에서는 상당히 느립니다. 보다 Agner Fog 's 최적화 안내서 및 지침 테이블. 커널 모드에서는 IF 및 AC 및 IO 권한 레벨을 변경할 수 있기 때문에 마이크로 코딩되었습니다. 디코더가 모드에 민감하지 않기 때문에 현재 CPU의 모드에 관계없이 페널티를받습니다.
가능하면 Pushf/POPF 대신 LAHF/SAHF를 사용하여 성능을 발휘하거나 같은 단일 플래그를 저장하십시오. setc al
그런 다음 나중에 add al, 255
설정 CF = (AL!=0)
. 또는 setnc al
/ sub al, 1
또는 무엇이든. 0 또는 1 레지스터를 기준으로 SF를 설정하거나 클리어링하기위한 시퀀스는 또한 플래그를 반전 시키거나없이 간단합니다.
다른 팁
깃발을 스택에 밀어 넣는 푸시프 및 POPF 지침을 사용하여 수정 한 다음 다시 팝업 할 수 있습니다.
플래그 레지스터의 하단 바이트 (SF, ZF, AF, PF, CF 포함) 만 필요하면 홀수이지만 편리한 명령 LAHF (HA HA)가있어 플래그의 하단 8 비트를로드합니다. 아, 그리고 상대방의 SAHF를 깃발에 보관합니다.
캐리 플래그의 경우, X86은 CLC, STC 및 CMC를 제공하여 각각 캐리 플래그를 지우고 설정 및 보완합니다.
가장 간단한 방법은 사용 중입니다 푸시/popf.
움직이고 싶다면 eflags
~ 안으로 eax
, 아래 코드를 사용하십시오.
pushf # push eflags into stack
pop %eax # pop it into %eax
setcc
이 명령 제품군은 깃발의 일부 플래그 / 조합을 관찰하는 또 다른 방법입니다.
개별 플래그를 기반으로 바이트 값을 설정합니다.
예를 들어, CF
:
stc
setc al
; al == 1
clc
setc al
; al == 0
어설 션과 함께 업스트림으로 실행 가능한 Github.
JCC
이 지침 제품군은 물론 특정 깃발의 또 다른 가능성이며 구현에 사용될 수 있습니다. SETcc
:
jc set
mov al, 0
jmp end
set:
mov al, 1
end:
- LAHF : 상태 플래그를 AH로로드합니다
- 부호, 0 및 운반 플래그를 포함하여 EFLAGS 레지스터의 낮은 바이트를 복사합니다.
보관을 위해 변수에 플래그 사본을 저장
.data saveflags BYTE ? .code lahf ; load flags into AH mov saveflags,ah ; save them into a variable
SAHF : AH를 상태 플래그에 저장합니다
- AH를 EFLAGS 레지스터의 낮은 바이트에 복사합니다.
이전에 저장된 플래그의 값을 검색하십시오
.code mov ah, saveflags ; load save flags into AH sahf ; copy into flags register