SMALL
- "본 내용은 Inflearn에 Rookies 강사님의 강의로 학습하고 있는 내용입니다."-
>>>> 이전 내용 : 산술연산자
이런 것들 수학을 하다보면 배웠을 것이다. 조금 다른 부분도 있지만 간단하다.
아래 코드 내용 부분에 이러한 부분이 있다 라고만 판단하고 읽으면 될 것 같다
중요한 것은
1. 연산자를 어떻게 사용하는가?
2. 연산자의 우선순위
3. 논리 연산자가 이루어지는 방식(최적화?)
분류 | 기호 | 설명 | result |
비교 연산자 | a > b | a의 값이 b보다 큰가? | a가 크다면 1 반환 b가 크다면 0 반환 |
a >= b | a의 값이 b의 값보다 크거나 같은가? | a가 크거나 같으면 1 아니면 0 | |
a < b | a의 값이 b 보다 작은가? | a가 작으면 1 아니라면 0 | |
a <= b | a의 값이 b보다 작거나 같은가? | a가 작거나 같으면 1 아니면 0 | |
a == b | a의 값과 b의 값이 같은가? | a와 b가 같다면 1 아니면 0 | |
a != b | a의 값과 b의 값이 다른가? | a의 값과 b의 값이 다르면 1 아니면 0 | |
논리 연산자 | a && b | 앞에 있는 조건과 뒤에 조건이 모두 만족하는가? | a의 조건도 b의 조건도 맞다면 1 아니면 0 |
a || b | 앞에 조건이든 뒤에 조건이든 하나라도 만족하는가? | a나 b의 조건 어느하나라도 맞으면 1 둘다 아니면 0 | |
!a | a는 아니다! (값을 뒤집어 준다) | a의 값이 true(1)면 false(0) , false(0)이면 true(1) |
코드 내용 >
더보기
/*비교& 논리 연산*/
#include <iostream>
using namespace std;
// 주제 : 데이터 연산
// 데이터를 가공하는 방법
int a = 1;
int b = 2;
bool isSame;
bool isDifferent;
bool isGreater;
bool isSmaller;
//논리
bool test;
int hp = 100;
bool isInvisible = true; // 무적여부
int main()
{
#pragma region 비교연산
// 언제 필요한가?
// ex ) 체력이 0이 되면 사망
// ex ) 체력이 30% 이하이면 궁극기를 발동 (100* hp / maxHp) 와 같이
// ex ) 경험치가 100 이상이면 레벨업
// a == b : a와 b의 값이 같은가?
// 같으면 1, 다르면 0
isSame = (a == b); // a가 b 같다면 1 틀리면 0 이 들어간다.
// a != b : a와 b의 값이 다른가?
// 다르면 1, 다르면 0
isDifferent = (a != b);
// a > b : a가 b보다 큰가?
// a >= b : a가 b보다 크거나 같은가?
// 1 아니면 0
isGreater = (a > b);
// a < b : a가 b 보다 작은가?
// a <= b : a가 b보다 작거나 같은가?
isSmaller = (a < b);
#pragma endregion
#pragma region 논리 연산
// 언제 필요? 조건에 대한 논리적 사고가 필요할 때 (여러 조건에 대한 판단)
// ex ) 로그인 할 때 아이디도 같고 AND 비밀번호도 같아야한다.
// ex ) 길드 해산 권한에 대한 길드 마스터 또는 어드민 계정이면 길드 해산이 가능하다 또는 둘 중 하나의 조건에 맞을 때 OR 논리연산자를 사용할 수 있다.
// ! not
// 0이면 1, 그 외 0
test = !isSame; // 뒤집어준다 사실상 isDifferent의 의미
// && and
// a && b -> 둘다 1일 경우 1 , 그외는 0 (즉 둘다 만족해야한다.)
test = (hp <= 0 && isInvisible == false); // 체력이 없고 무적도 아닌 것 = 죽음
// || or
// a || b -> 둘 중 한개만 1(true)여도 true 1, 둘다 0이면 0
test = (hp > 0 || isInvisible == true); // 체력이 남아있고 무적상태인 경우 = 생존
// !(hp <= 0 && isInvisible == false); 이런식으로도 만들 수 있다.
#pragma endregion
}
비교연산
isSame = (a == b); // a가 b 같다면 1 틀리면 0 이 들어간다.
00471856 mov eax,dword ptr [a (047A000h)]
0047185B cmp eax,dword ptr [b (047A004h)]
00471861 jne __$EncStackInitStart+33h (047186Fh)
00471863 mov dword ptr [ebp-0C4h],1
0047186D jmp __$EncStackInitStart+3Dh (0471879h)
0047186F mov dword ptr [ebp-0C4h],0
00471879 mov cl,byte ptr [ebp-0C4h]
0047187F mov byte ptr [isSame (047A1B8h)],cl
- a를 eax 레지스터에 넣어주고
- cmp : eax 와 b를 비교한다.
- jne(jump not equal) : 047186F(주소) h (16진수 형태 주소) 0047186F→ 으로 점프 하게끔 되어있다. 만약에 둘이 다르다 하면 0047186F mov dword ptr [ebp-0C4h],0 이 부분으로 와서 실행할 것이다. ebp-0C4h (스택주소) 스택 어딘가 0으로 셋팅해서 isSame을 false로 만드는 것
- 만약 jne를 통과 못했다면 둘이 같다는 얘기이니까. 00471863 mov dword ptr [ebp-0C4h],1 1값을 넣어주고 jmp 00471879 mov cl,byte ptr [ebp-0C4h] 점프해서 cl 레지스터에 넣어주는 것을 볼 수 있다.
- 그러니까. 0 이든 1이든 cl레지스터에 해당 값을 넣어서 isSame에 만들어준 곳에 결과물 바구니에 다시 넣어준다는 것
- 임시적으로 보관해서 최종적으로 넣어주는 것 (한 줄 이였던 게 이렇게 길게 작동한다)
isDifferent = (a != b);
00471885 mov eax,dword ptr [a (047A000h)]
0047188A cmp eax,dword ptr [b (047A004h)]
00471890 je __$EncStackInitStart+62h (047189Eh)
00471892 mov dword ptr [ebp-0C4h],1
0047189C jmp __$EncStackInitStart+6Ch (04718A8h)
0047189E mov dword ptr [ebp-0C4h],0
004718A8 mov cl,byte ptr [ebp-0C4h]
004718AE mov byte ptr [isDifferent (047A1B9h)],cl
isGreater = (a > b);
004718B4 mov eax,dword ptr [a (047A000h)]
004718B9 cmp eax,dword ptr [b (047A004h)]
004718BF jle __$EncStackInitStart+91h (04718CDh)
004718C1 mov dword ptr [ebp-0C4h],1
004718CB jmp __$EncStackInitStart+9Bh (04718D7h)
004718CD mov dword ptr [ebp-0C4h],0
004718D7 mov cl,byte ptr [ebp-0C4h]
004718DD mov byte ptr [isGreater (047A1BAh)],cl
isSmaller = (a < b);
004718E3 mov eax,dword ptr [a (047A000h)]
004718E8 cmp eax,dword ptr [b (047A004h)]
004718EE jge __$EncStackInitStart+0C0h (04718FCh)
004718F0 mov dword ptr [ebp-0C4h],1
004718FA jmp __$EncStackInitStart+0CAh (0471906h)
004718FC mov dword ptr [ebp-0C4h],0
00471906 mov cl,byte ptr [ebp-0C4h]
0047190C mov byte ptr [isSmaller (047A1BBh)],cl
논리연산
test = !isSame; // 뒤집어준다 사실상 isDifferent의 의미
00471912 movzx eax,byte ptr [isSame (047A1B8h)]
00471919 test eax,eax
0047191B jne __$EncStackInitStart+0EDh (0471929h)
0047191D mov dword ptr [ebp-0C4h],1
00471927 jmp __$EncStackInitStart+0F7h (0471933h)
00471929 mov dword ptr [ebp-0C4h],0
00471933 mov cl,byte ptr [ebp-0C4h]
00471939 mov byte ptr [test (047A1BCh)],cl
- isSame 바구니안에 값을 eax에 넣어주고 test라는 작업을 한다.
- test가 AND 연산이라고 생각하면 되는데 eax eax되어있는데jne (jump not equal)에 걸리면 해당 값이 0이 아니였다는 것
- “자기 자신이랑 하는데 왜 하지? 싶긴 하다. “ 이게 왜냐하면 결과물에 따라 ZeroFlag 가 영향을 받기 때문에, 연이어서 cmp 하고 점프 했던 것과 마찬가지로 test와 jne를 연이어서 응용할 수 있다는 것을 알 수 있다. 즉 eax , eax 하는 현재 지금 test는 0인지 아닌지 판별하는 것이다.
- 0이 아니였다면 00471929 mov dword ptr [ebp-0C4h],0 이곳 주소로 오게되어 점프해서 0을 집어넣고
- 만약 0이였으면 0047191D mov dword ptr [ebp-0C4h],1 ebp-0C4h 부분에 1을 넣어줬을 것이다.
- ebp-0C4h 는 스택프레임 어딘가 1 또는 0등이 들어간다(일종의 스택의 메모장 같은곳이다 임시저장소)
- 최종적으로 cl 레지스터에 넣어주고 cl레지스터의 값을 test에 넣어주는 것을 볼 수 있다.
✅ ZeroFlag와 Sign Flag
Zero Flag 연산 결과가 0이면 참(1)
Sign Flag(부호 플래그)
연산 결과가 음수이면 참(1)
죽었다는 것을 판단
test = (hp <= 0 && isInvisible == false); // 체력이 없고 무적도 아닌 것 = 죽음
0047193F cmp dword ptr [hp (047A008h)],0
00471946 jg __$EncStackInitStart+123h (047195Fh)
00471948 movzx eax,byte ptr [isInvisible (047A00Ch)]
0047194F test eax,eax
00471951 jne __$EncStackInitStart+123h (047195Fh)
00471953 mov dword ptr [ebp-0C4h],1 // 최종 (만약 전부 만족)
0047195D jmp __$EncStackInitStart+12Dh (0471969h)
0047195F mov dword ptr [ebp-0C4h],0
00471969 mov cl,byte ptr [ebp-0C4h]
0047196F mov byte ptr [test (047A1BCh)],cl
- cmp에서 hp 값과 0과 비교 하고 hp 가 양수이면 jg
- jg(jump greator) : 047195Fh 이곳 주소로 가서 0047195F mov dword ptr [ebp-0C4h],0 스택 어딘가 0이라는 값을 집어넣고 위 && AND 연산이 빠져나가서 바로 0이라는 결과를 알 수 있다.
- 앞에 hp <= 0 의 결과가 만족하지 않았으면 앞에 보지도 않고 바로 빠져나온다.
- jg 를 만족하지 않았다면 hp가 음수라는 것이 된다.
- isInvisible에 byte(바구니)를 뽑아와서 eax레지스터에 저장하고
- test eax, eax 값을 0인지 아닌지 판별한다.
- 만약 isInvisible이 true면 && 문이 만족을 안하니까. 최종적으로 실패해서 바로 0047195F mov dword ptr [ebp-0C4h],0 로 와서 빠져나올 테고
- 만약 다 통과 했다면 최종 결과물 00471953 mov dword ptr [ebp-0C4h],1 해당 값을 1로 셋팅해주고 cl로 다시 와서 test에 넣어주는 것을 볼 수 있다.
AND 연산의 특징을 볼 수 있듯이 먼저 왼쪽부터 체크를 하는 것을 볼 수 있다.
앞에 오느냐 뒤에 오느냐에 따라 성능 차이가 날 것으로 예상 된다.
test = (hp > 0 || isInvisible == true); // 체력이 남아있고 무적상태인 경우 = 생존
00471975 cmp dword ptr [hp (047A008h)],0
0047197C jg __$EncStackInitStart+15Ah (0471996h)
0047197E movzx eax,byte ptr [isInvisible (047A00Ch)]
00471985 cmp eax,1
00471988 je __$EncStackInitStart+15Ah (0471996h)
0047198A mov dword ptr [ebp-0C4h],0
00471994 jmp __$EncStackInitStart+164h (04719A0h)
00471996 mov dword ptr [ebp-0C4h],1
004719A0 mov cl,byte ptr [ebp-0C4h]
004719A6 mov byte ptr [test (047A1BCh)],cl
- 여기는 hp > 0이 만족하면 그냥 보지도 않고 바로 넘어갈 것이다.
- cmp 에서 hp에 값을 0인지 비교하는데 아니라면 jg 에 0471996 주소로 가서
- 00471996 mov dword ptr [ebp-0C4h],1 바로 여기로 넘어와서 1로 넘겨주는 것을 볼 수 있다.비교연산
728x90
728x90
LIST
'🅿🆁🅾🅶🆁🅰🅼🅼🅸🅽🅶 > C_C++' 카테고리의 다른 글
[C++과 언리얼로 만드는 MMO] C++ 기초_ 비트 연산과 비트플래그[Section3]{(20)} (2) | 2024.09.19 |
---|---|
[C++과 언리얼로 만드는 MMO] C++ 기초_산술연산자[Section3]{(18)} (5) | 2024.09.13 |
[C/C++_Doodle]BookReviewing_03_ 입력 받기 (0) | 2023.03.01 |