«   2020/07   »
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31  
Tags
more
Archives
Today
0
Total
1,731
관리 메뉴

넓적부리의 작업실

If~Else, Begin~End 명령어 구현 (2) 본문

CSharp/PEBakery

If~Else, Begin~End 명령어 구현 (2)

넓적부리 2016. 9. 22. 11:33

WinBuilder의 If 명령어는 다음 구조로 이루어져 있습니다.

If,<Condition>,<Command>

이 때 <Command>에는 사실상 거의 모든 명령어가 올 수 있기에, If의 중첩이 발생하는 등 처리가 매우 복잡해지게 됩니다. 그래서, 엔진에 명령어를 넣기 전에 컴파일해서 If 명령어의 구조를 간단하게 바꿔 구현하기로 결정했습니다.


If문을 구체적으로 어떻게 바꿀지 생각해 볼까요?


1. IfCompact, Jump 명령어 도입

1) IfCompact

IfCompact 명령어는 단순화된 If 명령어입니다.

형태 : IfCompact,<조건>

<조건>이 충족될 경우, IfCompact 한 줄 뒤의 명령어를 실행합니다.

<조건>이 충족되지 않은 경우, IfCompact 두 줄 뒤의 명령어를 실행합니다.


2) Jump

Jump 명령어는 C의 goto나 x86 어셈블리의 JMP와 같은 명령어입니다.

형태 : Jump,<상대/절대주소>,<숫자 N>

<상대주소>인 경우, Jump 명령어의 N줄 뒤의 명령어를 실행합니다. 이 때, n은 음수가 될 수도 있습니다.

<절대주소>인 경우, 현 섹션의 N번째 명령어를 실행합니다.



2. 경우에 따른 컴파일 결과

1) 단일 If 문

- 컴파일 전
If,%A%,Equal,B,Set,%C%,D
Echo,EndOfSection

- 컴파일 후
IfCompact,%A%,Equal,B
Set,%C%,D
Jump,Relative,1
Echo,EndOfSection

- 컴파일 후 (최적화)
IfCompact,%A%,Equal,B
Set,%C%,D
Echo,EndOfSetion

2) 단일 If 문 + 단일 Else 문

- 컴파일 전
If,%A%,Equal,B,Set,%C%,D
Else,Set,%C%,Z
Echo,EndOfSection

- 컴파일 후
IfCompact,%A%,Equal,B
Jump,Relative,2
Jump,Relative,3
Set,%C%,D
Jump,Relative,2
Set,%C%,Z
Echo,EndOfSection

- 컴파일 후 (최적화)
IfCompact,%A%,Equal,B
Jump,Relative,3
Set,%C%,Z
Jump,Relative,2
Set,%C%,D
Echo,EndOfSection



3) 블록 If 문

- 컴파일 전
If,%A%,Equal,B,Begin
Set,%C%,D
Set,%C%,E
Set,%C%,F
End
Echo,EndOfSection

- 컴파일 후
IfCompact,%A%,Equal,B
Jump,Relative,2
Jump,Relative,4
Set,%C%,D
Set,%C%,E
Set,%C%,F
Echo,EndOfSection

- 컴파일 후 (최적화)
IfCompact,Not,%A%,Equal,B
Jump,Relative,4
Set,%C%,D
Set,%C%,E
Set,%C%,F
Echo,EndOfSection


4) 블록 If 문 + 블록 Else 문

- 컴파일 전
If,%A%,Equal,B,Begin
Set,%C%,D
Set,%C%,E
Set,%C%,F
End
Else,Begin
Set,%C%,X
Set,%C%,Y
Set,%C%,Z
End
Echo,EndOfSection

- 컴파일 후
IfCompact,%A%,Equal,B
Jump,Relative,2
Jump,Relative,5
Set,%C%,D
Set,%C%,E
Set,%C%,F
Jump,Relative,4
Set,%C%,X
Set,%C%,Y
Set,%C%,Z
Echo,EndOfSection


위 예시들을 종합하면, If~Else, Begin~End 문을 다음과 같이 일반화할 수 있습니다.


5) 일반화

- 컴파일 전
If,<Condition>,Begin
(N commands)
End
Else,Begin
(M commands)
End
Echo,EndOfSection

- 컴파일 후
IfCompact,<Condition>
Jump,Relative,2
Jump,Relative,N+1

(N commands)

Jump,Relative,M+1

(M commands)

Echo,EndOfSection


이제 여기에 If~Else, Begin~End의 중첩을 고려하면 컴파일러를 어떻게 만들어야 하는지 어느 정도 윤곽이 잡히게 됩니다.

0 Comments
댓글쓰기 폼