Control Flow(cmp, test, jump, set instructions)(6)

G·2022년 10월 26일
0

2-2 System programming

목록 보기
4/15

Control Flow

조건이 있는 if문이나 loop를 내부적으로 어떻게 처리하는 지를 알아보자.
instruction을 어셈블리어로 확인하여 동작 방식을 알아보자.
컴파일 최적화 옵션은 -Og를 선택한다. -O0은 조금의 비효율성이 남아있고 -O1은 최적화가 강해 코드를 확인하기 어렵다.

Status register

status register는 CPU의 상태를 저장하는 레지스터이다. 산술연산이 발생할 때 overflow, carry(unsigned overflow), condtion 등을 condition code에 one bit(flag) 형태로 저장한다.
가장 일반적인 condtion code는 아래와 같다.

  • CF(Carray flag)
  • ZF(Zero flag)
  • SF(Sign flag)
  • OF(Overflow flag)

컴퓨터 아키텍쳐 마다 다르다.

add instruction

위에서 본 condtion codes들이 어떠한 방식으로 바뀌는 지 알아보자.
add instruction이 발생했을 때, 이를 t = a + b 형태로 보자.

  • CF: 최상위 비트가 바뀌었을 때 flag가 set된다.
  • ZF: t가 0일 경우 set된다.
  • SF: t가 0보다 작을 경우 set된다.
  • OF: signed overflow가 발생했을 경우 set된다.

cmp instruction

cmp instruction은 if문의 조건의 참 거짓을 판별할 때 사용되는 연산자이다.
cmp b, a 인 경우에 a - b의 형태로 참 거짓을 판별한다.
sub instruction은 a = a - b의 형태이지만 cmp는 결과값을 저장하지 않는다.

  • CF: 최상위 비트가 바뀌었을 때 flag가 set된다.
  • ZF: b와 a가 같을 경우에 set된다
  • SF: (a - b) < 0일 경우에 set된다
  • OF: 아래의 경우에 set된다.
    a와 b가 같은지 확인하려면 ZF가 set 되었는지 확인하면 된다.
    b가 a보다 작은 경우는 SF^OF(exclusive or)가 참인지 확인하면 된다.
    거짓일 경우 overflow가 일어난 것이다.
    b가 a보다 작거나 같은 경우는 (SF^OF)|ZF가 참인지 확인하면 된다.
    b가 a보다 큰 경우는 ~((SF^OF)|ZF)가 참인지 확인하면 된다.

test instruction

test b,a는 a&b bitwise 연산을 통해 condition에 저장한다.
ZF와 SF 두 가지 flag를 사용한다. +,-,0 셋 중에 bitwise의 결과가 무엇인지 확인한다.

크기에 따른 Instructions

Condition Code-Dependent Instruction

condition code에 dependent한 instruction들이다. jmp, set, cmov

  • jmp instruction: 조건에 따라 다른 instruction으로 이동한다.
  • byte를 0또는 1로 set한다.
  • cmov 조건적으로 변수를 옮긴다.

jmp instruction

예를들어 if(x > 100)이란 조건문이 있을 때 조건이 참이면 if문 스코프 안으로 들어가 연산을 수행한다. 만약 거짓이라면 jmp instruction이 수행되어 if 스코프 밖으로 이동하여 연산을 지속한다.

위는 jle instruction는 jump less or equal instruction이다. 첫 줄은 100과 첫 번째 매개변수를 저장하는 %rdi 레지스터의 비교이다. x - 100로 비교를하며 0보다 작거나 같을 경우 0xc 주소로 이동한다. if문 밖 다섯 번째 줄 return 값을 저장하는 %eax 레지스터의 연산이 있는 곳이다.


위의 이미지에서 .L1의 .는 주소를 뜻 한다. .L1의 주소로 점프하라는 것이다. C언어의 goto문을 생각하면 이해하기 수월하다.

mp instruction의 종류이다.

do-while & while


do-while과 while문의 작동원리이다.
.loop을 바로 타는 do-while문과 다르게 while문은 test라는 조건을 거치고 body로 들어간다.

do-while


위의 사진의 두 번째 줄을 보면 do-while의 조건문의 참 거짓을 따진다. cnt-100을 계산해 jg, 즉 0 보다 크다면 다시 do-while문의 스코프 안으로 들어간다. 0x0은 어셈블리어의 첫 번째 라인 주소를 뜻 한다.

while


위의 while문은 바로 jmp instruction이 나온다. 조건을 test하는 주소로 이동하는 것이다. 이는 한 번만 일어난다. 이후에 cnt-100이 0보다 크다면 jg가 일어나 body로 들어간다. 이후 반복적으로 cmp와 jg가 수행되어 거짓일 경우에 lea instruction으로 이동한다.

for


위는 for loop을 while loop으로 변환한 것이다. test로 goto 넘어가서 t를 처음에 초기화, 이후에 업데이트하고 조건이 참이라면 반복적으로 body로 들어간다.

while문과 똑같다. update 부분이 추가됐을 뿐이다.
처음에 i가 저장되어 있는 %edx 레지스터에 0을 초기화하고 test 문으로 jmp 한다.(0x14 부분을 보자.)
두 번째 매개변수 %rsi 레지스터에 저장된 n과 i를 비교한다. i-n이 0보다 작다면 body(0xc)로 이동한다. c를 보면 sum에 arr[i]을 더해주고 i를 update 해준다. add instructor를 사용하는 모습을 볼 수 있다.
이후 계속해서 비교를 해주며 반복한다.

set


set을 보면 첫 번째 두 번째 매개변수를 비교하여 x-y가 0보다 크다면(setgreater) 1을 레지스터에 저장한다. 이후 리턴값을 저장하는 %rax에 옮겨주는 것을 확인할 수 있다.

profile
열심히 안 사는 사람

0개의 댓글