※ 질문/내용오류/공유할 내용이 있다면 jinkilee73@gmail.com으로 메일 주세요 :-)


오랜 만에 포스팅을 하는 것 같다. 요즘 포스팅에 재미가 들리다 보니까 애초의 나의 의도와는 다른 사심이 생겼다. 방문자 수;;; 이게 은근히 재미가 쏠쏠하다. 비록 맛집이나 제품 사용 후기 또는 프로그래밍과 같은 주류의 블로그는 아니지만 나름 하루에 대략 25~30명은 온다. 나름 쏠쏠한 재미. 내 본래의 의도를 되세기며 다시 한번 포스팅을 해보자.


오늘은 Conditional Jump에 대해서 이야기를 해볼 생각이다. 조건적으로 점프하는 것이다. 물론 여기에서 말하는 점프란, 코드 상에서의 점프를 말하는 것이다. 이 정도는 다들 아실 것이라 믿는다.


우선, 어셈블리 언어에서 점프를 어떤 원리를 통해서 수행하는지를 설명해보도록 하자. 이번 포스팅에서는 실제로 jmp명령어에 대한 이야기는 나오지 않을 예정이다. jmp 명령어를 수행하기 전에 jmp할 조건을 어떻게 세팅하는지에 대한 설명이 주를 이룰 것이다.


어떻게 점프를 하는가? 한 마디로 말하면 레지스터 값을 변경하여 그 값에 따라 점프를 수행한다. 지금까지 언급되어왔던 %ebp, %esp, %eax와 같은 값들과는 다른 레지스터 값이다. 바로 CF, ZF, SF, OF값들이다. 이 네가지의 값들을 적당히 바꿔서 그 값으로 연산해서 점프한다. 무슨 말인가 싶을 것이다. 차근 차근 알아보자.


CF, ZF, SF, OF는 각각 1바이트로 전부 4바이트의 크기를 차지하는 레지스터이다. 각각의 의미를 알아보자.

CF : Carry Flag : 연산시 Carry가 발생하면 1로 세팅된다. 오버플로우를 탐지하는데 쓰이기도 한다.

ZF : 가장 최근에 계산된 명령어의 결과값이 0이면 1로 세팅된다.

SF : 가장 최근에 계산된 명령어의 결과값이 음수면 1로 세팅된다.

OF : 가장 최근에 계산된 명령어가 2's complement 오버플로우를 일으키면 1로 세팅된다.


아직까지도 의문인 점이 있을 것이다. 저 값들을 도대체 어떻게 세팅을 하곘다는 것인가? 답은 '저절로 세팅된다' 이다. 어셈브릴 명령어는 두 가지로 구분될 수 있다. CF ZF 등등과 같은 Condition Code(CC)에 영향을 주는 명령어와 그렇지 않은 명령어.


대부분의 산술/논리 연산 명령어는 CC에 영향을 준다. 가령,

%ebx = -5, %ecx = 5일 때


add        %ebx, %ecx

계산할 때 %ecx값이 0으로 세팅되었다고 하자. 그러면 저절로 ZF는 1로 세팅된다. 또한 SF는 0으로 세팅되겠지? 0이 음수는 아니니까. 그리고 OF는 0으로 세팅된다. 오버플로우는 없었으니까. CF도 0이다. 딱히 Carry가 발생하지 않았으니까.


leal명령어는 CC값을 전혀 바꾸지 않는다. 아무리 leal명령어를 수행해도 CC값은 전혀 변하지 않는다는 뜻이다. leal 명령어 같은 경우 다른 레지스터 값은 수정할 수 있지만 CC는 수정할 수 없는 명령어이다. 반대로 CC만 수정할 수 있고 다른 레지스터 값은 바꿀 수 없는 명령어들도 있다. 대표적으로 test명령어와 cmpl명령어가 있다.


cmpl 명령어부터 설명해볼까? cmpl 명령어는 두 개의 파라미터를 갖는다. 다음과 같은 명령어를 수행했다고 가정하자.


cmpl        %ebx, %eax


이럴 경우, 다음과 같은 계산들이 수행된다.

우선 두 개의 파라미터를 뺀다. (%eax - %ebx) 여기서 중요한 점이 있다. 뺄셈을 진행했을 때 그 값은 어디에도 저장되지 않는다는 것이다. 뺄셈한 값이 0이든 100이든 -100이든 신경쓰지 않는다. 신경쓰는 것은 오로지 다음의 네 가지 사항들이다.


1. Carry가 있는가? 있으면 CF를 1로 세팅

2. 뺄셈한 값이 0인가? 0이면 ZF를 1로 세팅

3. 뺄셈한 값이 음수인가? 음수면 SF를 1로 세팅

4. 오버플로우가 발생헀는가? 발생했으면 OF를 1로 세팅


test 명령어를 설명하면 다음과 같다. cmpl이 CC의 모든 값에 영향을 준 반면, test 명령어는 CC 중에서 ZF와 SF만 영향을 주고 CF와 OF는 무조건 0으로 세팅한다. 가령 다음의 test 명령어가 있다고 하자.


test        %ebx, %eax


이럴 경우, 다음과 같은 계산들이 수행된다.

이전에 cmpl에서는 두 개의 파라미터를 뺐던 반면, test 명령어의 경우 두 개의 파라미터 값에 대해 &연산을 한다. %ebx & %eax를 계산한 후, 다음의 두 가지를 신경쓴다.


1. 연산한 결과가 0인가? 0이면 ZF를 1로 세팅

2. 연산한 결과가 음수인가? 음수면 ZF를 1로 세팅


왜 test 명령어에서 CF와 OF는 무조건 0으로 세팅될까? CF와 OF가 1이 될 수가 없기 때문이다. 생각해봐라. 어떤 숫자를 &연산을 하는데 어떻게 Carry가 발생하며 오버플로우가 발생할 수 있남?


도대체 이러한 결과들을 가지고 어떻게 점프를 한다는 것인지 아직은 감이 안올 것이다. 다음 포스팅에서는 cmpl과 test 명령어를 통해 어떻게 점프를 하고 더욱 나아가 어떻게 C코드의 if문 혹은 for문을 구현할 수 있는지를 설명하겠다.

'System Programming' 카테고리의 다른 글

[SP] Optimizing a program with a hardware independent perspective  (1) 2013.05.21
[SP] Conditional Jump  (1) 2013.05.14
[SP] Procedure Call  (0) 2013.05.04
[SP] Assembly Language Example  (0) 2013.04.30
[SP] Assembly Language  (1) 2013.04.30
Posted by 빛나유
,