분기문 하기에 앞서 사칙연산을 정리해보겠다.

사칙연산하는 C코드의 어셈블리어는 어떻게 구성될까?



(C코드)




컴파일 후 확인해본다!




(어셈블 코드)



저번 글에서 만들었던 형태가 비슷하게 나오는 것을 확인 할 수 있다.

오늘은 분기문을 공부 할 것이다.
jmp는 해당 주소로 이동하는 것이다.

이것을 이용하면 조건문도 만들 수 있고 반복문도 만들 수 있다.
실제로 C코드에서 if와 switch는 jmp 명령어로 이루어져있고
어셈블 차원에서 보면 똑같다.

사용 형식은
jmp addr
이런식으로 써준다.

그렇다면 jmp로 무한루프를 만들어보겠다.




(무한루프 코드)



jmp 명령에 의해 _start로 돌아간다.
_start는 레이블 이름으로 주소값이다. 컴파일 전에 주소값을 우리는 모르니 레이블 이름을 달아주어 사용한다.
컴파일한다.



(컴파일)



컴파일 후 실행해보면



(실행 모습)



실행되는 모습이다.

그렇다면 C코드의 기본적인 if문을 어셈블러로 구현해보자!
먼저 C코드의 기본적인 if문 코드이다.



(if문 코드)




(실행모습)



여기서는 조건 분기를 사용한다. 위의 jmp는 무조건 분기로 다른 조건없이 바로 해당 주소로 넘어가지만 조건분기는 조금 다르다.

조건 분기
 - EFLAGS 레지스터를 참조해서 분기할지 말지를 결정한다.
조건 분기문을 쓰기전에 cmp를 해줘야 EFLAGS에 기록하고 이걸 보고 조건문기문이
동작한다.

 - cmp

조건분기 종류를 살펴보면
 - je (jmp equal) = jz
 - jne (jmp not equal) = jnz
 - jl (jmp less)
 - jg (jmp greater)
 - jnl
 - jng
 - jle
 - jge
 - ja (jmp above) 초과
 - jb (jmp below) 미만
 - jna
 - jnb
 ...

3. cmp : 비교명령어
 cmp vleft vright
 -> 두개의 값이 같은지 비교
- vleft 값과 vright 값의 차를 구한다.
- 그 결과에 따라서 EFLAGS 레지스터의 플래그를 조절한다.
cmp에서 사용하는 flg
- ZF, SF
1) vleft - vright의 결과가 0인 경우
 : ZF = 1, SF=0 -> 두 값이 같다고 판단
2) vleft - vright의 결과가 음수인 경우
 : ZF=0, SF=1 -> 오른쪽이 더 크다.
3) vleft - vright의 결과가 양수인 경우
 : ZF=0,SF=0
조건분기문 사용 직전에 cmp를 해줘야한다.

이를 이용해 기본적인 if C코드를 어셈블러 코드로 구현하면 아래와 같다.



(조건분기문 사용)




(실행결과)



실행 결과 잘 나오는 듯하다.
(하지면 이 코드에는 문제점이 있다.)

값을 5보다 작게 2로 설정하여 확인해보겠다.



(작은 값 입력)




(실행결과)



실행결과를 보니 2가 작음에도 크다고 출력되었다.

왜 이럴까??
원인은 바로 점프하지 않고도 그 아래에 출력해주는 명령문이 있기 때문에 아래 코드가 순차적으로 실행 되었던 것이다. 이것을 막아주기 위해서는 아래 처럼 추가해주면된다.



(추가 코드)




(실행결과)



실행한 결과 작을 때는 이제 출력되지 않는 우리가 원하던 C코드의 동작을 하게 되었다.

다르게 표현을 하자면 jmp문 하나로도 완성 가능하다.



(다른 표현)



C코드를 컴파일 한 내용과 비교해보겠다.
상수끼리 비교하면 컴파일러가 알아서 계산을 해놓아서...
변수를 따로 선언을 해주었다.



(C코드 수정)



컴파일 후 어셈블러를 확인해보면



(어셈블 코드)



우리가 만든 코드와 비슷하게 나온 것을 확인 할 수 있다.

그렇다면 실습으로 아래와 같은 코드를 어셈블 코드로 만들어보자!



(실습 코드)



실습 결과는 아래와 같이 만들 수 있다.



(실습 결과)



jmp 문에 대한 내용이었다.



+ Recent posts