[6] 어셈블리 비트연산 ( shift, and, or, not )

2017. 10. 20. 19:55SystemHacking/Assembly






1. 비트 연산 ( Shift 연산 )

1-1. 부호가 없는 연산

shl : 왼쪽으로 이동

shr : 오른쪽으로 이동



1-2. 부호가 있는 연산

sal : 왼쪽으로 이동

sar : 오른쪽으로 이동


[ C언어에서 shift 연산 ]

int eax=4;

eax << 1     // 8  = 4 * 2

eax << 1     // 16 = 8 * 2

eax << 1     // 32 = 16 * 2


-> 4 * 2 * 2 * 2 ...

4:00000100 => 16:00010000



2. 논리 연산 ( and, or, not )

2-1. and

1 and 1 = 1

0 and 0 = 0

1 and 0 = 0

0 and 1 = 0


1 or 1 = 1

0 or 0 = 0

1 or 0 = 1

0 or 1 = 1


2-2.xor

초기화할 때 주로 사용한다 ( xor eax, eax )


1 xor 1 = 0 

1 xor 0 = 1

0 xor 1 = 1

0 xor 0 = 0 


2-3. neg ( =not )

not 1 = 0

not 0 = 1

=> neg 명령어로 사용한다 부호를 변경할때 사용한다

      mov     eax,    15

      neg     eax

=> eax 레지스터에는 -15가 저장되어 있다


나눗셈에서의 shift 연산 활용


  mov     eax,    0            ; eax 레지스터 초기화

        mov     ax,     10           ; ax 레지스터( 16bit ) 에 10 입력

        mov     dl,     4             ; dl 레지스터 ( 8bit ) 에 4 입력

        div     dl                      ; ax 레지스터 / dl 레지스터 : 16bit / 8bit => AH(나머지):AL(몫

        shr     ax,     8              ; ax >> 8


        push    eax

        push    argv

        call    printf 




16bit 10을 8bit 4로 나눌때

AL:몫 , AH:나머지 저장된다

AX 레지스터의 형태

 00000010

00000010 

 AH

AL 


AX >> 8 쉬프트 연산을 하여 구할수 있다 - 나머지 값 !

AL 은 그냥 출력하면 된다 - 몫값 !



나눗셈에서의 and 연산 활용

        mov     eax,    0            ; eax 레지스터 초기화

        mov     ax,     10           ; ax 레지스터 ( 16bit ) 에 10 입력

        mov     dl,     4             ; dl 레지스터 ( 4bit ) 에 4 입력

        div      dl                      ; ax / dl , AH(나머지):AL(몫)

        

and   eax,    FFh ; or 00000000000000000000000011111111b

        push    eax

        push    argv

        call    printf

 


EAX 레지스터

 00000000  

 00000000

 00000010 

 00000010

 


 AH ( 나머지 )

 AL ( 몫 )


AX와 0xFF and 연산

00000010(AH) 0000 0010(AL)

0000 0000 1111(F) 1111(F)

=> 00000000 00000010 => AL 을 구할 수 있다 ( 몫 ! ) 



3. 형변환

3-1. 작은 곳에서 큰 곳으로

movzx ( zero extend ) 부호 없는 경우

movsx ( sign extend ) 부호 있는 경우


        xor     eax,    eax

        mov     dl,     10

        mov     eax,    dl

=> invalid combination of opcode and operands 오류발생 ! 

=> 32bit 레지스터에 8비트 값을 이동시키려고 하니까!

movzx eax, dl

movsx eax, dl

mov 대신 사용하자



3-2. 큰 곳에서 작은 곳으로 


eax -> ax -> al

xor     eax,    eax

mov   edx,    10

mov   ax,     dx

mov ax, word [memory]

명령어가 따로 필요없다