간단 지식/System Programming

07. condition code - 상태 레지스터, setX 명령어, jX 명령어

납작한돌맹이 2020. 11. 19. 23:10
반응형

실행 중인 프로그램에 대한 정보(processor state)는 크게 아래 4개로 분리할 수 있다.

1. temporary data

2. location of runtime stack

3. location of current code control pointer

4. status of recent test

임시 데이터는 레지스터 %rax, %rbx 등에 저장되어있다. runtime stack의 위치는 스택포인터 %rsp에 저장된다. 현재 코드의 구조포인터는 %rip 에 저장된다. 최근 테스트에 대한 상태는 상태 레지스터를 조직하는 flag bit들에 저장된다. 이번 글에서 다룰 내용은 4번에 해당하는 상태 레지스터이다.


상태 레지스터는 status register 또는 flag register라고도 하며, 산술 연산 결과의 상태를 알려주는 status bit(=flag bit)들이 모인 레지스터이다. 이 레지스터는 조건문과 같은 실행의 분기점에 사용되기 때문에 condition code(조건코드)라고 통칭하기도 한다. flag bit에는 CF(carry flag), ZF(zero flag), SF(sign flag), OF(overflow flag), IF(interrupted flag), PF(parity flag), TF(trap flag) 등이 있으며, 각각 1bit를 가진다.(여기서는 CF, ZF, SF, OF에 대해서만 정리를 할 것이다)

flag bit Implicit
CF MSB(최상위비트)에서 carry out이 발생했을 때 T
ZF 연산 결과가 0일 때 T
SF 연산 결과가 음수일 때 T
OF 연산 결과의 2의 보수가 overflow이면 T

OF에 대한 간단한 팁이 있다. 연산자가 addq이고 피연산자가 a, b, 이고 연산결과를 t라고 가정한다면, (a>0 && b>0 && t<0) || (a<0 && b<0 && t>=0) 과 같은 조건식을 이용할 수 있다. 어찌됐던 가장 최근에 실행한 연산결과에 따라 flag bit의 값은 각각 변화한다.

 

연산의 피연산자들은 implicit setting이냐 explicit setting이냐에 따라 차이가 있다. 각 용어의 의미를 먼저 알아보자면, implicit은 tool의 관점에서, 기본적으로 내포된 구조를 의미하며 개발자는 이를 호출만 할 수 있다(ex.자바의 class, data type) explicit은 개발자의 관점에서, 직접 코드를 write할 수 있는 것을 의미한다(ex. getname1(), setname2())

 

다시 setting으로 돌아와서, implicit setting은 addq, subq 처럼 산술연산의 피연산자가 src, dest이다. 반면에 explicit setting은 피연산자가 src, dest가 아니라 src1, src2로, destination을 setting하지 않아도 된다. 이에 해당하는 명령어는 cmpq와 testq이다.

cmpq는 compare instruction으로, -를 통해 두 피연산자 src1, src2의 대소관계를 비교한다. 

ex) cmpq src1, src2 

     src2 - src1 == 0 이면 ZF = 0, src2 - src1 < 0 이라면 SF = 0 으로 set된다.

testq는 두 피연산자 src1, src2의 & 연산을 계산한다.

ex) testq src1, src2

     src1 & src2 == 0 이면 ZF = 0, src1 & src2 < 0 이라면 SF = 0으로 set된다.


4개의 flag bit의 조합에 따라 연산자들의 대소관계가 결정된다. 그리고 이 조합들을 쉽게 사용할 수 있도록 setX instruction이 존재한다.

setX condition description
sete ZF equal or zero
setne ~ZF non equal or not zero
sets SF negative
setns ~SF nonnegative
setg ~(SF^OF) & ~ZF greater (signed)
setge ~(SF^OF)  greater or equal (signed)
setl ~SF^OF)  less (signed)
setle ~(SF^OF) | ZF less or equal (signed)
seta ~CF & ~ZF above (unsigned)
setb CF below (unsigned)

setX instruction은 condition code의 조합에 근거한 single byte를 setting한다. 그러다보면 1byte 이상의 타입을 다루는 경우 잔여 byte가 생길 수 있다. 아래 예시를 보자.

int test(long x, long y){
    return x>y;
}

test: cmpq %rsi, %rdi
      setg %al
      movzbl %al, %eax
      ret

변수 x와 y값을 비교할 것이고, 그를 위해서는 x-y 연산을 해야하므로 %rdi = x, %rsi = y 이다. cmpq 연산을 통해 4개의 condition code의 값은 0 또는 1로 set된다. 그와 동시에 x가 y보다 더 크면 %al = 1, 아니면 %al = 0 이 된다. 이때 cmpq와 setg는 동시에 진행되야 하므로 이 사이에 새로운 코드라인이 추가될 수 없다. 만일 추가되면 상황에 맞게 setting 되었던 flag bit 값들이 변하기 때문에 올바른 값을 return 할 수 없다.

어찌됐던 다음 라인으로 넘어가서 movzbl이라는 명령어가 보인다. %eax에 %al을 대입한다는 것인데 %eax는 4byte고 %al은 1byte이다.(%eax를 사용하는 이유는 return type이 4byte인 long이기 때문이다) 연산 후 남는 3byte가 빈공간이라면 차라리 상관없는데 레지스터는 공유되는 하드웨어 자원이기 때문에 쓰레기값이 들어가있을 수도 있다. 따라서 movzbl를 이용하면 3byte를 0으로 채울 수 있다.


setX와 유사하게, condition code에 의존하여 코드의 다른 부분으로 이동하는 명령어가 jX instruction이다.

setX condition description
jmp 1 unconditional
je ZF equal or zero
jne ~ZF non equal or not zero
js SF negative
jns ~SF nonnegative
jg ~(SF^OF) & ~ZF greater (signed)
jge ~(SF^OF)  greater or equal (signed)
jl (SF^OF)  less (signed)
jle ~(SF^OF)| ZF less or equal (signed)
ja ~CF & ~ZF above (unsigned)
jb CF below (unsigned)

jX 명령어는 c언어의 goto와 동일한 역할을 한다. 아래 예시를 보자.

long test(long x, long y){
        long result;
        if(x>y)
                result = x-y;
        else
                result = y-x;
        return result;
}

test:
        movq    %rdi, %rax
        cmpq    %rsi, %rdi
        jle     .L2        ----------(1)
        subq    %rsi, %rax
        ret
.L2:
        subq    %rdi, %rsi
        movq    %rsi, %rax
        ret

test함수는 x>y일 때 x-y를, x<y일 때 y-x를 실행한다. 따라서 if와 else의 분기점에 jump 명령어가 있어야 하기 때문에 코드라인 (1)처럼 jle 명령어가 등장한다. 전체 어셈블리어를 해석해보면 먼저 cmpq명령어로 x와 y를 비교한다. 그리고 jle 명령어로 x와 y가 less or equal인지 확인한 후 참이면 아래의 subq 명령어를, 거짓이라면 L2로 점프하여 subq 명령어를 실행한다.

 

 

(이 글이 도움이 됐다면 광고 한번씩만 클릭 해주시면 감사드립니다, 더 좋은 정보글 작성하도록 노력하겠습니다 :) )

반응형