Flag Register : 1비트로 쉽게 Boolean 값이다. 특정 상태 등을 알리기 위해 사용한다.
대표적으로...
CF(Carry Flag) : 연산 과정에서 발생되는 Carry, Borrow. 즉 덧셈 뺄셈에서 나오는 올림 및 내림.
PF(Parity Flag) : 결과 값의 1의 개수가 짝수면 1, 홀수면 0. 오류 검출에 사용됨
ZF(Zero Flag) : 연산 결과가 0이면 1, 아니면 0. 비교 연산에서 두 값이 같은지 확인
SF(Sign Flag) : 연산 결과의 부호를 나타냄. 음수면 1, 양수면 0.
OF(Overflow Flag) : 오버플로우가 발생했으면 1, 아니면 0
이런 Flag Register들을 이용하는 주된 곳은 Jump Instruction이다.
Jump Instruction의 구조는 j[Operation] [Address] 이다.
이때, Address는 메모리 주소이며, 조건을 만족할 시 이동할 주소이다.
Operation은 검사할 조건의 약자를 사용한다.
- O, NO (Overflow, Not Overflow) : 플래그 OF를 검사한다.
- S, NS (Sign, Not Sign) : 플래그 SF를 검사한다.
- E, Z (Equal, Zero) : 플래그 ZF를 검사한다.
이외에도 G, GE, L, LE (Greater/Less [Equals]) 등이 있다.
이때, Jump Instruction은 플래그만 확인하며, 이 플래그를 셋하기 위해 점프 앞에 cmp, test 등의 플래그를 셋하기 위한 Instruction Code가 위치하게 된다는 것을 주의해야한다. 또한, 해당하는 Operation을 만족하는 경우에 점프를 한다.
Flag를 이용하는게 Jump라면, Jump를 이용하는 건 무엇일까?
Jump를 주로 이용하는 프로그래밍 코드는 If, Switch와 같은 조건문과 for, while과 같은 반복문이다.
먼저 조건문을 살펴보자.
If문의 경우, 매 조건을 검사하며 아니면 점프하는 방식을 가진다. 아래와 같은 방식이다.
cmp ~ ; 조건1 검사
jne line5; 조건1 불만족시 line5로 점프
(equals 일 때 실행) 조건1 만족할 때의 실행 코드
jmp line11; if문 탈출
cmp ~ ; 조건2 검사
jne line9; 조건2 불만족시 line9로 점프
(equals 일 때 실행) 조건2 만족할 때의 실행 코드
jmp line11; if문 탈출
(else 실행) else코드
jmp line11; if문 탈출
...
Switch문의 경우 If문과 달리, 각 case에서 break;를 넣지 않으면 아래로 쭉 지속되던 것을 기억할 것이다.
그 이유를 여기서 알 수 있는데, If문의 비교-실행-비교-실행 구조가 아니라, 비교-비교..-실행-실행.. 의 구조이다.
특히, 간단한 1,2,3,.. 과 같은 연속된 case를 가진 Switch문의 경우, 테이블을 이용해 최적화된다. 그 구조는 아래와 같다.
코드가 case 1:, case 2:, case 3: default: 일 때,
mov rax, 입력값;
cmp rax, 3;
jg line16; 입력값이 3보다 크면 deafult로 이동
jmp line(6+rax); 입력값에 따라 line7~9 중에 이동
jmp line10; 입력값이 1이면, case 1 코드로 이동
jmp line12; 입력값이 2면, case 2 코드로 이동
jmp line14; 입력값이 3이면, case3 코드로 이동
(case1코드)
jmp line18; break의 효과, default 다음으로 이동
(case2 코드)
jmp line18; break의 효과, default 다음으로 이동
(case3 코드)
jmp line18; break의 효과, default 다음으로 이동
(default 코드)
...
이런 방식이 어려운 경우, 각각의 값에 대해 cmp를 걸 수도 있다.
코드가 위와 같을 때,
mov rax, 입력값;
cmp rax, 1;
je line11; 입력값이 1이면, 해당하는 line11로 이동
cmp rax, 1;
je line13; 입력값이 2면, 해당하는 line13으로 이동
cmp rax, 1;
je line15; 입력값이 3이면, 해당하는 line15로 이동
jmp line17; case를 모두 지나왔으므로, default로 이동
(case1코드)
jmp line18; break의 효과, default 다음으로 이동
(case2 코드)
jmp line18; break의 효과, default 다음으로 이동
(case3 코드)
jmp line18; break의 효과, default 다음으로 이동
(default 코드)
...
다음으로 반복문에 대해 알아보자.
for문은 어셈블리에서 [변수 초기화-증감-비교-코드]순으로 되어 있으며, 첫 반복에서는 증감 부분을 스킵한다.
그 구조는 아래와 같다.
for문을 for( state1(초기화) ; state2(비교) ; state3(증감) ) { state4(코드) } 라고 할 때,
...
state1;
jmp state2;
state3;
state2;
[jump]; // state2의 결과가 false면 for문 밖으로 점프
state4;
jmp state3;
...
while문은 for와 달리 구조도 단순하므로, [비교-코드] 순으로 되어있다.
while( cond ) { state }의 구조라고 할 때,
...
cond
[jump] // 만약 false라면 while 바깥으로 점프한다.
state
jmp cond
...
for문에 비해 간략한 모양새지만, 초기화 부분이 없는걸 감안하면 구조 자체에 큰 차이는 없다.
'4-1공부 > 리버스엔지니어링' 카테고리의 다른 글
[기말고사] 12. DLL & DLL Injection (1) | 2023.06.18 |
---|---|
[기말고사] 10-11. PE & IAT (1) | 2023.06.18 |
[기말고사] 9. 호출 규약 (0) | 2023.06.18 |
[중간고사] asm1 (0) | 2023.04.16 |