[역난독화]gcc optimize option-컴파일 시 생략되는 분기문[2/2]

1 minute read

-o가 아닌 다른 컴파일 옵션들

-o0, -o2,-o3,… 등 여러 컴파일 옵션이 있는데, 지난 시간에 이걸 적용해보려고 시도했는데 실패했었다. 다시 도전해보니 커맨드라인을 잘 못 작성한 것이였다.

$ gcc -o2 sourcecode.c

위와 같은 명령어를 실행하면 2(옵션의 번호).exe라는 이름의 실행파일이 생성된다. -o옵션의 경우

$ gcc sourcecode.c -o target.exe

이렇게 작성해야하는데, -o를 제외한 옵션을 실행하기 위한 명령어는 타겟 파일의 이름을 작성하지 않고, 옵션의 위치가 다르다.

gcc로 컴파일 시 생략되는 분기문

지난 주차에 gcc로 코드를 컴파일해보고, optimize 한 결과를 살펴보았다. 그 결과, if(para*para>0) 과 같은 조건문이 생략되는 것을 발견하였다. 그래서 이번 주차에는 컴파일 시에 어떤 비교문이 생략되는지 조사하였다. 여러번 테스트해본 결과, 테스트케이스가 간단하기 때문에 컴파일 옵션별로 특별한 차이가 없었다. 그렇기때문에 컴파일 옵션 결과는 하나만 업로드하였다.

1. 연산이 없는 정수를 이용한 비교문

[1] 비교 기준 값이 하나인 경우

image

위의 코드에 대하여 컴파일된 어셈블리 코드는 다음과 같다.

image

비교문이 매우 간단하였는데 분기문이 사라지지 않고 존재한다. 컴파일되면서 분기문이 생략될 줄 예상하였는데, 예상과 다른 결과였다.

[2] 비교 기준 값이 두개인 경우

image

변수에 별도로 연산을 수행하지 않았지만, 범위 구간을 나누도록 하여 비교문을 작성하였다. 어셈블리 코드는 다음과 같다.

image

2. 정수의 제곱 값 이용한 비교문

[1] 양수, 대소 비교

image

image

양수를 제곱하여 0보다 큰지 비교하는 비교문에 대해서는 jmp가 사용되는 분기문이 생략되었다.

[2] 음수, 대소 비교

image

image

정수가 음수인 경우에도 제곱하여 비교하면 jmp문이 사라지는 모습을 확인할 수 있었다.

[3] 양수, 0과 같은지 비교

image

image

분기문이 유지되어있다.

3. 정수의 세제곱을 이용한 비교문

[1] 양수, 0보다 작은지 비교

image

image

[2] 음수, 0보다 작은지 비교

image

image

[3] 양수, 0과 같은지 비교

image

image

위의 [1][2][3] 세 경우 모두 분기문이 생략되지 않고 유지되는 것을 확인하였다.

결론

비교에 사용되는 변수가 제곱연산 되어있고, 대소비교하는 경우에 분기문이 생략된다른 추론을 할 수 있다.

네제곱한 경우에는 테스트해보지 않았지만, 그대로 비교하거나 세제곱한 경우 (승의 수가 홀수인 경우)에는 비교문이 그대로 유지되었다. 이를 보아 승의 수가 짝수인 수를 대소비교할 경우에는 분기문을 생략한다는 결론을 낼 수 있다.