본문 바로가기
전공/시스템 프로그래밍

[시스템 프로그래밍 8-1]Boolean and Comparison Instructions (어셈블리어에서 불린 연산자)

by 뜨거운 개발자 2023. 4. 28.

Boolean and Comparison Instructions

if와 else에 대해서 공부하기 전에 미리 boolean 연산자에 대해서 보겠다.

인텔 명령어 세트에는 이미 부울 연산 명령어가 포함되어있다.

이 표에서는 보이는 TEST연산은 아마 익숙치 않을텐데 간단하게 설명하면 AND와 같은 연산인데 결과를 저장하지는 않는 것이다. 뒤에서 왜 쓰는지 보겠다.

The CPU Status Flags

  • 부울 명령은 Zero, Carry, Sign, Overflow, and Parity flags 에 영향을 준다.
  • 작업 결과가 0과 같으면 0 플래그가 설정됩니다.
  • 캐리 플래그는 연산이 대상 피연산자의 가장 높은 비트의 캐리를 생성할 때 설정됩니다.
  • Sign 플래그는 대상 피연산자의 상위 비트의 복사본입니다.
  • 오버플로 플래그는 명령이 대상 피연산자의 부호화된 범위를 벗어나는 결과를 생성할 때 설정됩니다.
  • 패리티 플래그는 명령이 대상 피연산자의 로우 바이트에 짝수 1비트를 생성할 때 설정됩니다.

1. AND Instruction

AND 명령은 두 피연산자와 AND 연산자로 하고 결과값을 dest에 배치한다.

AND destination,source

  • 허용되는 피연산자 조합은 다음과 같다.
  • 피연산자는 8, 16, 32 또는 64비트일 수 있으며 피연산자 사이의 크기는 같아야한다.
  • imm 피연산자는 32비트 이하여야만 한다.

AND연산자의 주된 사용처

a. 비트마스킹(masking)

주어진 비트 중 특정 비트만을 지우고 싶을 때 (특정비트를 끄고 싶을 때) 사용을 한다.

예시 : and AL, 11110110b → 0비트와 3번비트만 0으로 꺼주고 나머지는 원상태를 유지한다.

b. 플래그

  • AND 명령은 항상 오버플로와 캐리플래그를 지운다.!! (항상 0으로 세팅된다.)
  • 대상 피연산자(dest operation) 에 따라서 부호, 0, 패리티 플래그를 수정한다. (결과에 따라서 달라진다는 것)

c. 문자를 대문자로 변환

  • AND 명령은 문자를 소문자에서 대문자로 쉽게 변환하는 방법을 제공한다.
  • 대문자 A와 소문자 a의 아스키 코드를 비교하면 5번 비트만 다르다는 것을 알 수가 있다.

11011111 바이너리가 있는 문자를 AND하면 지워지는 비트 5를 제외한 모든 비트가 변경되지 않습니다.

대문자로 바꾸기 예시코드

array 안에 문자열이 들어와 있다고 생각하기

이 코드는 모든 문자를 대문자로 변환합니다.

.data
array BYTE 50 DUP(?)
.code
    mov ecx,LENGTHOF array
		mov esi, OFFSET  array
L1 : and BYTE PTR [esi],1101111b ; clear bit 5
		 inc esi
		 loop L1

2. OR Instruction

OR destination, source

  • 허용되는 피연산자 조합은 다음과 같다.

피연산자는 8, 16, 32 또는 64비트일 수 있으며 크기가 같아야 합니다.

두 피연산자에서 일치하는 각 비트에 대해 입력 비트 중 하나 이상이 1이면 출력 비트는 1이 됩니다.

OR연산은 다른 비트에 영향을 주지않고 특정 비트를 세팅할 때 주로 사용이 된다.

2번 비트를 켜고 싶을 때 or AL, 00000100b

플래그

  • OR 명령은 항상 오버플로와 캐리플래그를 지운다.!! (항상 0으로 세팅된다.)
  • 대상 피연산자에 따라 부호, 0, 패리티 플래그를 수정합니다.
  • AND와 동일

3. Bit-Mapped Sets

집합의 형태로 비트를 사용할 수 있다. 각 비트별로 정보를 담는 용도로 쓰는 것.

  • 집합을 비트 맵으로 표현할 수 있는 것이다.

[예시] 특정 멤버가 집합에 있는지를 학인하기

mov eax,SetX
and eax, 10000b ;4번비트에 원소가 있는지 아닌지를 검사한다. (4가 멤버가 맞는지 검사)

연산의 결과를 보면 zero 플래그 하나만을 확인해서 결과를 알 수 있기 때문에 유리하다.

여집합 구하기

  • 집합의 보수는 모든 비트를 반전시키는 NOT 명령어를 사용하여 생성할 수 있습니다.

교집합 구하기

  • AND 명령은 두 집합의 교집합을 나타내는 비트 벡터를 생성합니다.
  • 다음 코드는 SetX와 SetY의 교집합을 생성하여 EAX에 저장합니다
mov eax,SetX
and eax,SetY
  • 이것이 SetX와 SetY의 교집합이 생성되는 방식이다.
  • 이걸 사용하는 이유는 cpu가 제공하는 연산중에 가장 빠르기 때문에 활용하면 강력한 무기가 됩니다!

유니온 설정하기 (합)

  • OR 명령은 두 집합의 합을 나타내는 비트 맵을 생성합니다.
  • 다음 코드는 EAX에서 SetX와 SetY의 합집합을 생성합니다.
mov eax,SetX
or eax,SetY
  • 이것이 OR명령에 의해 SetX와 SetY의 합이 생성되는 방식이다.

4. XOR Instruction

  • 리버서블한(Reversible)" 프로퍼티이다.(이전 작업이나 변화를 거꾸로 되돌릴 수 있는 속성을 의미한다.)
    • XOR은 동일한 피연산자에 두 번 적용하면 스스로 반전됩니다
  • 시메틱(Symmetric)한 인크립션(Incryption)을 할 수 있다.(대칭적인 암호화를 할 수 있다.)
    • XOR의 이러한 "가역적" 속성은 간단한 형태의 대칭 암호화에 이상적인 도구입니다.

플래그

  • XOR 명령은 항상 오버플로 및 캐리 플래그를 지웁니다.
  • XOR은 대상 피연산자에 따라 부호, 0 및 패리티 플래그를 수정합니다.

앞선 2개의 연산과 같음

패리티 플래그 확인

  • 패리티 검사는 숫자에 포함된 1비트 수를 세는 이진수에 대해 수행됩니다.
  • 패리티 플래그가 무엇인가? 주어진 결과의 마지막 8비트를 본다.(낮은자리)
  • 여기서 비트가 짝수개인지 홀수개인지 확인을 하는데 짝수개이면 1 홀수개이면 0으로 세팅해준다.
  • 데이터 동일성을 비교하는데, 사용을 주로 한다.

주어진 레지스터에 pairaty를 체크하는 것을 보여주는 예제

숫자의 값을 변경하지 않고 숫자의 패리티를 확인하는 효과적인 방법은 배타적이거나 0이 있는 숫자를 사 용하는 것입니다

mov연산은 플래그에 영향을 안준다!!

이 예제에서는 0과 xor를 해본다. (1이면 1 0이면 0이 나오는 결과)

  • 연산을 했기 때문에 pairity flag를 볼수가 있다.
  • 이 예제에서는 첫번째 수는 홀수여서 flag가 0이고 두번째는 짝수개여서 1이다.

주의!! 32비트짜리 레지스터를 보더라도, 가장 하위 8개비트(1바이트)에서만 1의 갯수를 세서 패러티 플래그를 설정해준다.

하위 2바이트(16비트 패러티)를 측정하고 싶은 상황이라면..?

  • 상위 1바이트와 하위 1바이트의 비트를 XOR해주면 16비트 패리티를 알 수가 있다!!
  • 실제 16비트에서는 메모리 저장이 AX (16 bit) [AX] = [AH][AL]
  • 이 두개의 메모리를 XOR해주면..! pairty flag가 세팅이 16비트에 대해서 설정이 된다.!!

5. NOT Instruction

  • 모든 비트를 반전한다. (토글해준다!!!)
  • 그 결과를 1의 보수를 구하는 것이다.
  • Flag레지스터에 영향을 주지 않는다.

6. TEST Instruction

  • TEST 명령은 AND 연산을 수행하지만 대상 피연산자를 수정하지 않는다.(AND와 유일한 차이점)
  • TEST 명령은 AND 명령과 동일한 피연산자를 허용한다.
  • TEST는 피연산자의 개별 비트가 설정되어있는지 확인하는데 특히 유용하다!!!

[예시] 주어진 A레지스터에서 0번이나 3번비트가 세팅여부 확인 예시

  • 그러면 0이 아닌데 ZERO FLAG가 세팅되는 경우가 발생하는 것이다!!

flag레지스터

  • TEST 명령은 항상 오버플로 및 캐리 플래그를 지웁니다.
  • AND 명령과 동일한 방식으로 부호, 0, 패리티 플래그를 수정합니다.

7. CMP Instruction

test와 유사한 연산을 하는 연산자.

주어진 피연산자를 비교하는 역활을 한다. 주로 대소 비교(>, <) 할 때 많이 사용되는 연산자이다.

실제로 비교는 SUBSTACTION을 하는 것 뿐이다. 다만 이 연산은 DESTINATION(피연산자)를 업데이트 하지 않는다. (뺄셈을 시도해보는 것 뿐..!)

  • 두 피연산자 모두 수정되지 않습니다
  • CMP는 AND 명령과 동일한 피연산자 조합을 사용합니다.
  • 문자 코드도 정수이므로 CMP에서도 작동합니다.

플래그

따라서 이 연산의 결과로 SUBSTRACTION 한것과 같은 변화가 발생한다!!

  • 컴퓨터는 주어진 숫자가 signed인지 unsigned인지 모른다!!
  • 따라서 singed인지 unsigned인지에 따라서 어떤 flag를 체크해야하는지 달라진다!!
  • 앞에서 뒤에거를 빼는것!!!
  • 부호있는 경우 :
    • 작은 수에서 큰 수를 빼면 음수가 되는 경우인데 OF가 발생하지 않아야한다
    • 큰수에서 작은수를 뺐는데 SF가 발생하지 않아야한다!!
    • 이건 비정상적인 결과가 나왔을 때 OVERFLOW가 발생할 수있다는 것!!!!!!

플래그 확인 예시

9. Setting and Clearing Individual CPU Flags

  • 캐리플래그를 세팅하거나 지우는 경우 명령어가 주어진다.
    • STC : 캐리플래그 설정 명령
    • CLC: 캐리플래그 삭제 명령
  • ZERO FLAG
    • ZERO FLAG를 세팅하고 싶으면 0과 TEST 또는 AND연산을 하면 세팅할 수 있다.
    • ZERO FLAG를 없애고 싶으면 0이 아닌 것을 OR연산하면 된다.
  • Sign FLAG
    • 사인비트 클리어 하고 싶으면 최상위 비트가 0인 녀석과 AND 하면된다.
    • 사인 세팅하고 싶으면 최상위 1일 때 OR
  • OVERFLOW
    • 세팅하고 싶으면 최상위 값에서 1을 더해주면 된다.
    • 아무 boolean 연산을 하면 clear 가능하다.

Uploaded by N2T

728x90