전공/시스템 프로그래밍

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

뜨거운 개발자 2023. 4. 28. 11:15

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