[7] 어셈블리 분기문 ( if, switch ) +cmp, jmp

2017. 10. 23. 19:19SystemHacking/Assembly





1. cmp ( compare )

레지스터나 메모리의 값을 변경하지 않는다

플래그 레지스터에만 영향을 준다 ( flag register - 상태 레지스터 )

-> SF(부호), CF(올림수), ZF(0,두개의 비교값이 같을 때 )


# 두 피연산자의 비교 ( CMP )

cmp eax, ebx

=> eax-ebx 

=> 결과가 0인 경우: 같은 경우 => SF:0, CF:0, ZF : 1

=> 결과가 음수인 경우 : eax < ebx => SF:1 , CF:0, ZF: 0

=> 결과가 양수인 경우 : eax > ebx => SF:0, ZF:0 , CF:0


0번이 시작

7번 플래그() - SF 

6번 플래그() - ZF


cmp 10, 20

1  0 000111

SF ZF 

cmp 10,10

0  1  000110

SF ZF

cmp 20,10

0  0  010110

SF ZF



2. 분기문

2-1. 무조건 분기문 : jump 명령을 사용한다


jmp [ address | offset ] : 특정 주소나 offset 으로 점프한다


2-2. 조건 분기문 ( flag를 기준으로 jmp 실행 결정 )


JA Jump Above 

JG Jump Grater

JGE Jump Grater Equal <-> JNL Jump Not Less


JB Jump Below

JL Jump Less

JLE Jump Less Equal <-> JNG JUMP Not Grater


JC Jump Carry ( CF=1 )

JS Jump Sign  ( SF=1 )

JZ Jump Zero  ( ZF=1 )



[ 분기문 예제 1 ]


extern printf


section .data

prompt_int:     db      '%d', 10, 00

prompt_less:    db      'less!!', 10, 00

prompt_grater:  db      'grater!!',10, 00


section .text

global main


main:

mov     eax,    3330    

cmp     eax,    20        ; eax reg 와 20 비교

jl      if                      ; eax < 20 이라면 if 레이블로 점프 ( Jump Less )

jge     else                 ; eax >= 20 이라면 else 레이블로 점프 ( Jump Grater Equal )

if:

push    prompt_less

call    printf

jmp     end

else:

push    prompt_grater

call    printf

end:




[ 분기문 예제 2 ] 

if ( eax == 0 && ebx >= 1 && ecx < 2 )    { edx = 1 }

else   { edx = 0 }


extern printf


section .data

prompt_int:     db      '%d', 10, 00

prompt_less:    db      'less!!', 10, 00

prompt_grater:  db      'grater!!',10, 00


section .text

global main


main:

mov     eax,    0

mov     ebx,    2

mov     ecx,    1

cmp     eax,    0     ; eax reg 와 0 비교

jne     else     ; not equal           => jump else

cmp     ebx,    1           ; ebx reg 와 1 비교

jl      else              ; less => jump else

cmp     ecx,    2       ; ecx reg 와 2 비교

jge     else              ; grater or equal         => jump else

if:

mov     edx,    1

jmp     end ; 모든 조건식이 만족하므로 else 실행하지 않기위해 end 로 점프한다

else:

    mov     edx,    0  

end:

push    edx

push    prompt_int

call    printf ; if ( eax == 0 && ebx >= 1 && ecx < 2 )    edx = 1

; else    edx = 0 



[ 분기문 예제 3 ]

if ( eax == 0 || ebx >= 1 || ecx < 2 ) { edx = 1 }

else { edx = 0 }


extern printf


section .data

prompt_int:     db      '%d', 10, 00

prompt_less:    db      'less!!', 10, 00

prompt_grater:  db      'grater!!',10, 00


section .text

global main


main:

        mov     eax,    1

        mov     ebx,    0

        mov     ecx,    4


        cmp     eax,    0

        je      if                 ; eax reg 와 0을 비교해서 equal 이라면 if로 jump


        cmp     ebx,    1

        jge     if                 ; ebx reg 와 1을 비교해서 equal 이라면 if로 jump

; eax, ebx 가 모두 거짓이여서 ecx까지 비교를 수행할 때,

        cmp     ecx,    2                         ; ecx reg 와 2를 비교한다

        jnl     else                         ; ecx 비교결과 not less 이라면 else 로

; 즉 모든 조건이 거짓인 경우가 된다

if:

        mov     edx,    1

        jmp     end

else:

        mov     edx,    0

end:

        push    edx

        push    prompt_int

        call    printf                         ; if ( eax == 0 || ebx >= 1 || ecx < 2 ) edx = 1

; else edx = 0

 


[ 분기문 예제 4 ]

if ( ( eax == 0 && ebx >= 1 ) || ecx < 2 ) { edx = 1 }

else    { edx = 0 }


extern printf


section .data

prompt_int:     db      '%d', 10, 00

prompt_less:    db      'less!!', 10, 00

prompt_grater:  db      'grater!!',10, 00


section .text

global main


main:

mov     eax,    1

mov     ebx,    0

mov     ecx,    4


cmp     eax,    0            ; eax reg 와 0 을 비교

jne     third                  ; eax 가 0 이 아니라면 ( Not Equal ) Jump  !


second:                                ; eax = 0 조건이 만족되어 순서대로 코드가 진행되었다

cmp     ebx,    1             ; ebx reg와 1을 비교한

jge     if                        ; ebx >= 1 이라면 if 레이블로 Jump !


third:                                    ; eax 조건식이 거짓일 때 점프해서 왔다

cmp     ecx,    2             ; ecx reg와 2를 비교한다

jnl     else                     ; ecx reg >= 2 라면 else 레이블로 Jump !


if:                                        ; eax와 ebx 조건식이 모두 참이면, 문제의 조건식은 무조건 참이다

mov     edx,    1             ; C언어 표현의 if ( True ) { edx = 1 } 이 실행된다

jmp     end

else:                                     ; eax 나 ebx 의 조건식이 거짓이면서 ecx의 조건식이 거짓일 때, 문제의 조건식은 거짓

mov     edx,    0             ; C언어 표현의 else { edx = 0 } 이 실행된다

end:

push    edx

push    prompt_int

call    printf                 ; if ( (eax == 0 && ebx >= 1 ) || ecx < 2 ) edx = 1

; else    edx = 0