태초의 프로그래밍 언어 어셈블리

assembly, 8086, x86

참과 거짓을 구별할때 쓰는 논리 연산

컴퓨터로 판단해야할 때가 많습니다. 사용자가 마우스 클릭을 했는지 안했는지 키보드를 눌렀는지 안눌렀는지 엑셀에서 셀들의 합이 100을 넘는지 안넘는지 하나의 프로그램에 얼마나 많은 판단이 들어가는지 모릅니다.

컴퓨터로 하는 판단을 논리 연산이라고 부릅니다. logic operation이라고 하는데 어떤 연산 결과가 내가 생각하는 결과와 같냐 다르냐를 판단하는 연산입니다. 루프를 예로 들면 10번 반복해서 화면에 'A'를 출력하고 싶을 때 현재 몇번 출력했는지를 기억해놨다가 10번이 되었는지 안되었는지를 판단해야합니다. 이럴때 횟수와 10을 비교해서 횟수가 10보다 작은지를 판단합니다. 이런게 논리 연산입니다.

플래그 레지스터

플래그 레지스터라는 것이 있습니다. 에물레이터를 실행해보면 아래쪽에 있는 버튼들 중에 가장 오른쪽에 flags라는 버튼이 있습니다. 이 버튼을 누르면 현재 플래그 레지스터의 상태를 보여줍니다.

이 그림이 생각나시나요? 오른쪽 아래에 이름은 안써있지만 Overflow, Direction 등등 16개의 사각형이 있습니다. 이게 플래그 레지스터입니다. 

이 레지스터는 16비트인데 각 비트마다 어떤 의미를 가집니다. 각각의 비트에 대해서 설명하겠습니다. 비트니까 당연히 1아니면 0이겠지요? 1은 해당하는 상태가 맞다는 의미이고 0은 해당 상태가 아니라는 것입니다.

Carry Flag (CF) - 부호없는 정수가 overflow일경우 플래그값은 1로 설정됩니다. 무슨 말이냐면 al에 255를 넣고 1을 더하는 연산을 하는 경우에 결과값이 범위가 8비트 범위 0 ~ 255를 넘게되고 이런 상태를 overflow라고 부릅니다. overflow가 아닌경우에는 플래그 값은 0으로 남아있습니다.

Zero Flag (ZF) - 결과값이 0일때 1로 설정됩니다. 같은 레지스터끼리 아니면 같은 값을 가진 레지스터끼리 빼기를 하면 0이 되지요. 결과값이 0이 아닐경우 플래그 값은 0이됩니다.

Sign Flag (SF) - 결과값이 음수일경우 1이 됩니다. 양수일때는 0이 되고요.

Overflow Flag (OF) - 부호 있는 정수끼리의 연산에서 overflow일경우 1이 됩니다. 예를들어 100 + 50할 경우입니다.(결과값 범위가 -128...127이 아니므로) Carry Flag와는 다릅니다. 

Parity Flag (PF) - 비트값이 1인것이 짝수이면 1로 설정하고, 홀수이면 0으로 설정한다. 결과값이 word이고, 8 low bit이어도 분석을 한다.

Auxiliary Flag (AF) - 부호 없는 정수 nibble(4 비트)이 overflow일경우 1로 설정한다.

Interrupt enable Flag (IF) - CPU가 외부 장치에 의해 인터럽트를 반응할때 1로 설정한다.

Direction Flag (DF) - 이 플래그는 명령어에 의해 data chain이 처리 될때 사용된다. 프로세싱이 메모리 앞 번지에서 뒷번지로 진행될때는 0로 설정되고 프로세싱이 메모리 뒷번지에서 앞번지로 진행 될때는 1로 설정된다.

 

 

org 100h
mov al, 100
mov bl, 50
add al, bl

mov al, 255
mov bl, 1
add al, bl
ret

 

100과 50을 더했습니다. 그런데 100은 al 레지스터에 있고 50은 bl 레지스터에 있네요. 각각 8비트 레지스터입니다. 따라서 8비트끼리의 더하기이므로 150이란 결과값에 overflow 상태가 될까요 carry 상태가 될까요? 레지스터 전체의 범위를 벗어나지 못했으니 carry가 없고 overflow만 있는 것입니다. carry란 가능한 범위를 벗어나는 것을 말합니다.

예제를 실행하면서 어떤 플래그 비트들이 1로 바뀌는지 확인해보세요.

논리 연산 명령어

논리 연산을 실행하는 CMP, AND, TEST, OR, XOR, NOT 명령어들을 하나씩 실험해보겠습니다.

and, or, xor, not 명령어는 이름 그대로의 연산을 합니다. 예제를 실행해볼까요.

org 100h
 
mov ax, 1
mov bx, 0
and ax, bx
 
mov ax, 1
mov bx, 0
or ax, bx
 
mov ax, 1
mov bx, 0
xor ax, bx
 
mov ax, 1
mov bx, 0
not ax
not bx
 
mov ax, 1
test ax, ax
test ax, 1
 
ret

1 and 0, 1 or 0, 1 xor 0, not 1, not 0 연산을 한번씩 실험해보는 소스입니다. 

1 and 0의 결과는 뭔가요? and 연산이라는 것은 두가지 모두 참이어야 결과가 참이되고 하나라도 0이면 거짓인 연산입니다. 따라서 1 and 0은 0이지요. 실험을 하면서 잘 봐야할 것은 레지스터 값이 어떻게 바뀌느냐와 어떤 플래그가 바뀌느냐 입니다. ax가 1이고 bx가 0인 상황에서 and ax, bx 명령의 결과값인 0이 어디에 저장되나요? ax입니다. ax의 값이 1에서 0으로 바뀌었습니다. 그리고 zero 플래그가 1로 바뀌었습니다. 연산 결과가 0이니까요. 그 외에 overflow나 carry는 변하지 않습니다. and ax, bx를 and bx, ax로 바꿔서 해보세요. 결과값이 어디에 저장될까요? and ax, bx를 실행할 때와 상태 플래그가 같나요?

test 명령은 약간 특이한 명령입니다. 하는 일은 and와 동일한데 차이는 레지스터의 값을 바꾸지 않습니다. 상태 레지스터만 바꿉니다. 그래서 test입니다. 값이 같은지 0이 아닌지를 테스트하는 것입니다. test ax, ax 이렇게 같은 레지스터를 테스트하면 레지스터의 값이 0인지를 확인하겠다는 것이고, test ax, 1 로 실행하면 ax 레지스터의 값이 1인지 0인지를 확인하는 것입니다. test ax, 1 명령이 실행되고 zf가 1이되면 (ax and 1)의 결과값이 0이라는 뜻이니까 ax가 0이겠지요? 

흥미유발?을 위해서 다른 명령어에 대한 설명은 하지 않겠습니다. 직접 해보세요. 문서로 백장 천장 쓰고 읽어봐야 한번 실행해서 이것저것 실험해보는것만 못합니다.

 

 

댓글

댓글 본문
작성자
비밀번호
  1. 학생이노
    감사합니다
    대화보기
    • gurugio
      연산은 숫자 계산을 말합니다. 사칙연산이나 논리연산등을 말합니다.
      대화보기
      • 학생이노
        mov ax,0
        이렇게 해도 0 플래그는 변화가 없습니다.
        대입연산자는 0을 대입해도 플래그에 변화가 없는 것 같아요
        그럼 연산의 결과에 따라 플래그가 변화한다는 것에서 연산이란 정확하게 무엇인가요?
      • ㅇㅇ
        CF, OF 이해가 안가네요.. 0xff 는 부호있는 정수(-127) 도 부호없는 정수(255)도 모두 될 수 있는거 아닌가요??
        그냥 부호비트가 1이 되면 OF, 결과가 1바이트를 넘어가면 CF

        아닌가요..ㅠㅠ
      버전 관리
      gurugio
      현재 버전
      선택 버전
      graphittie 자세히 보기