지금까지 C나 java를 통해 간단하게 조건문을 사용했었다.
그렇다면 컴파일러는 조건부 구조를 어떻게 기계어로 변환하는지 알아보자.
블록 구조의 IF 문
high level language에서 조건문은 아래와 같이 표현한다.
if( op1 == op2 )
X = 1;
else
X = 2;
이런 간단한 논리적 구조를 어셈블리언어로 변환하면 다음과 같다.
mov eax,op1
cmp eax,op2
jne L1
mov X,1
jmp L2
L1:mov X,2
L2:
사실상 JE 명령어로 == 연산자를 구현한 셈이다. 물론 이 방법만 있는 것은 아니며 여러가지 방법이 있다.
학교 ppt에는 바로 다음으로 넘어가긴 했지만 책에 나온 if 중첩문 예시가 한번쯤 생각해 볼 만 한것같다.
if op1 == op2 then
if X > Y then
call Routine1
else
call Routine2
end if
else
call Routine3
end if
이와 같은 high level 언어를 어셈블리어로 변환해보면
mov eax, op1
cmp eax, op2
jne L2
; inner IF-ELSE statement process
mov eax, X
cmp eax, Y
jg L1
call Routine2
jmp L3
L1: call Routine1
jmp L3
L2: call Routine3
L3:
AND를 사용한 복합 표현식
논리적 AND 연산을 구현할 때, 고급 프로그래밍 언어들의 단락평가 short-circuit evaluation를 고려하자.
( 단락 평가는 논리 연산을 수행할 때, 전체 결과를 결정하기 위해 필요한 최소한의 계산만 수행하는 평가 방식 )
예를 들어 if문의 첫 번째 표현식이 false라면, 두 번째 표현식은 스킵된다.
if (al > bl) AND (bl > cl)
X = 1;
이와 같은 논리는 어셈블리어로 다음과 같이 변환할 수 있다. (다른 방식으로도 가능)
cmp al,bl ; first expression...
ja L1
jmp next
L1:
cmp bl,cl ; second expression...
ja L2
jmp next
L2: ; both are true
mov X,1
next:
추가예시
if( ebx <= ecx && ecx > edx )
{
eax = 5;
edx = 6;
}
cmp ebx,ecx
ja next
cmp ecx,edx
jbe next
mov eax,5
mov edx,6
next:
OR을 사용한 복합 표현식
OR문 역시 AND 연산과 마찬가지로 단락평가를 고려해야 한다.
예를 들어 or문의 첫 번째 표현식이 true라면, 두 번째 표현식은 스킵된다.
if (al > bl) OR (bl > cl)
X = 1;
우리는 여기에서 switch case 문에서 배웠었던 fall-through를 사용할 수 있다.
cmp al,bl ; is AL > BL?
ja L1 ; yes
cmp bl,cl ; no: is BL > CL?
jbe next ; no: skip next statement
L1:mov X,1 ; set X to 1
next:
WHILE 루프
while 루프는 사실상 IF 문 다음에 루프의 몸체가 나오고, 그 다음에 무조건 루프의 맨 위로 점프하는 것과 같다.
while( eax < ebx)
eax = eax + 1;
이것을 어셈블리어로 구현하면 다음과 같다.
top:cmp eax,ebx ; check loop condition
jae next ; false? exit loop
inc eax ; body of loop
jmp top ; repeat the loop
next:
테이블 기반 선택
다중 선택 구조 대신에 테이블 검색을 사용하는 방법이다.
이 방법을 사용하기 위해서는 검색 값과 레이블 또는 프로시저의 오프셋을 포함한 테이블을 만들어야 하고 테이블을 검색하려면 루프를 사용해야 한다.
이런 방식은 비교를 많이 해야할 때 도움이 된다.
우선, 조회할 값과 프로시저의 offset을 포함하는 테이블을 생성해보자.
.data
CaseTable BYTE 'A' ; lookup value
DWORD Process_A ; address of procedure
EntrySize = ($ - CaseTable)
BYTE 'B'
DWORD Process_B
BYTE 'C'
DWORD Process_C
BYTE 'D'
DWORD Process_D
NumberOfEntries = ($ - CaseTable) / EntrySize
이 코드의 프로시저 offset 테이블을 표현하면 각 프로시저가 어디에 있는지 알 수 있다.
다음으로, 루프를 사용하여 테이블을 검색한다.
일치하는 항목이 발견되면, 현재 테이블 항목에 저장된 프로시저 오프셋을 호출한다.
mov ebx,OFFSET CaseTable ; point EBX to the table
mov ecx,NumberOfEntries ; loop counter
L1: cmp al,[ebx] ; match found?
jne L2 ; no: continue
call NEAR PTR [ebx + 1] ; yes: call the procedure
call WriteString ; display message
call Crlf
jmp L3 ; and exit the loop
L2: add ebx,EntrySize ; point to next entry
loop L1 ; repeat until ECX = 0
L3:
finite-state machine (FSM)
finite-state machine (FSM)는 상태 전이 다이어그램 이라고도 부르며, 입력에 따라 상태가 변경되는 기계나 프로그램을 말한다.
FSM은 그래프를 사용해서 표현한다.
정사각형이나 원은 노드라고 하며, 화살표로 표현하는 edge가 있다.
화살표로 표현하는 만큼, directed graph로 불린다.
각각의 노드는 시작 또는 종료 상태로 지정되고, 종료 상태는 굵은 선의 사각형으로 나타낸다.
FSM은 임의의 기호 시퀀스(문자열)를 받아서 토큰으로 변환하고, 이를 수용 상태(최종 상태)로 전환시킬 수 있다.
언어 규칙(정규 표현식)에 의해 지배되는 문자 시퀀스를 인식하거나 검증하는 데 사용할 수 있다.
이런 그래프를 이용하는 것으로 프로그램의 제어 흐름을 시각적으로 추적할 수 있다.
게다가 수정이 쉽고 어셈블리 언어로 쉽게 구현할 수 있다.
StateA:
call Getnext ; read next char into AL
cmp al,'+' ; leading + sign?
je StateB ; go to State B
cmp al,'-' ; leading - sign?
je StateB ; go to State B
call IsDigit ; ZF = 1 if AL = digit
jz StateC ; go to State C
call DisplayErrorMsg ; invalid input found
jmp Quit
상태 A에 대한 flow chart는 다음과 같다.
'언어 > 어셈블리' 카테고리의 다른 글
Advanced Procedures - 스택 프레임, 재귀 (0) | 2024.06.21 |
---|---|
정수 연산 소개 (산술, 논리) SHL, SAL, ROL, RCL, SHLD (0) | 2024.06.13 |
조건부 명령어들 (cmp 명령어, 조건부 jump, loopz) (0) | 2024.05.23 |
스택을 이용한 프로시저 실행 과정 (0) | 2024.04.21 |
데이터 전송, 주소 지정과 산술 연산 (0) | 2024.04.21 |