본문 바로가기
프로그래밍/SYSTEM HACKING

[SYSTEM HACKING] 명령어( mov, lea )

by B T Y 2017. 10. 18.
반응형

명령어( mov, lea )에 대해서 정리한다.




! 데이터를 저장할 수 있는 곳


    -  메모리

    - 레지스터

    - 코드섹션



명령어


1. mov


  - 할당 연산자와 비슷한 개념

  - mov dst, src


  ! 피연산자 dst, src가 둘 모두 메모리가 올수는 없다.


  !! 코드섹션에서 메모리를 사용할때는 주소에 대한 메모리의 크기를 명시해준다.

     ( 주소에 대한 메모리의 크기를 명시해주지 않으면 nasm은 해당 주소의 크기를 data 혹은 bss 섹션에 정의해놔도 

       코드를 실행할때는 알지 못한다 )


       * 레지스터의 크기는 이름으로 알 수 있지만 메모리는 이름으로 크기를 알 수 없다.


       * 코드 섹션에 mov 명령어를 사용할 때 피연산자로 레이블 이름을 그대로 적어주고 상수 값을 주는건 

          피연산자로 상수, 상수를 주는것과 같기 때문에 에러가 발생한다.

         ( mov 명령어에 피연산자를 줄때 메모리, 메모리와 상수, 상수인 상황을 제외하고는 사용이 가능하다 )


       * CPU 설계상 동시에 두 개의 메모리를 접근할 수 없다.

       * 어셈블리에서는 +, - 같은 연산자로 연산을 할수 없고 add와 같은 명령어를 사용하지만 

          Effective Address 주소를 +, - 등과 같은 연산자를 이용해서 연산할 수 있다.



( nasm 공식 홈페이지를 참조하면 Effective Address에 대한 사용법과 자세한 설명이 나와있다 )


* 참고로 [ ] 안에서 연산을 통해 다음 주소로 접근할때 +로 메모리 크기만큼 숫자를 늘려가는 방법 말고도 *(스케일)을 이용할 수도 있다.

( 다만, 용할때 주의할 점은 메모리크기는 1, 2, 4, 8 byte바께 없기 때문에 *로 3을 곱하거나 하면 안된다는 점이다.




( mov 명령어에는 들어가는 피연산자 두개의 역할을 위 코드로 예를 들면

10의 값을 읽어와서 eax라는 레지스터에 할당하는것이다 )



( 여기서는 num은 그냥 주소 그 자체이기 때문에 결국 mov 명령어 피연산자에는

상수, 상수를 넣은것과 같아서 상수를 읽어와서 상수에 넣는다는 말이니 에러가 난다... )



( nasm을 이용해서 어셈블링 과정을 진행해보면 에러가 나는데 

mov 명령어가 사용된 19번째 줄에서 에러가 발생했고 피연산자를 줬을때 나타나는 에러이다 )



( 여기서는 [ ] 안에 주소를 넣어 줬지만 해당 메모리의 nasm이 알 수가 없기 때문에

'operation size not specified'라는 에러가 나게 된다.. )



( 위와 같이 dword라는 크기를 주소 앞에 적어줘야 nasm은 해당 주소의 크기를 알수 있다 )


 * data, bss segment에 정의되어 있는 부분과는 별개로 코드 섹션에서 작성할때는 

주소 앞에 크기를 적어줘야한다..




( 여기서 10이 아닌 num의 주소값이 출력된건 마찬가지로 push를 해서 넘겨줄때 

nasm은 num의 주소 크기를 알수도 없기 때문이다... )



( 해당 부분을 고쳐서 dword [num]과 같이 작성하게 된다면 정상적인 출력이 가능해진다.. )



( 이번에는 data segment에 4byte 크기의 test_1 레이블에 값을 100으로 주고

해당 내용을 출력해본다..

여기서는 mov 명령어의 피연산자를 줄때 test_1의 메모리 값을 읽어와서

eax라는 레지스터에 넣도록 되어있다 )


* 레지스터의 경우 이름만으로도 크기를 알 수 있기 때문에 메모리와는 다르게 

이름만 적어줘도 된다.




( data segment에 string 레이블에 값인 'korea', 10, 00에서 첫번째 문자(1byte)만 

가져와서 출력 해보는 코드이다... )




( 이번에는 'korea', 10, 00에서 두번째 문자인 'o'를 가져와서 출력해보는데

이때 Effective Address는 [ ] 안에서 +, - 연산자를 이용해서 연산이 가능하기 때문에 이점을 이용한다..

byte 크기의 메모리에서 다음 인덱스의 값을 가져오기 위해서는 +1을 해주면 된다 )



( 결과에서 보이는것과 같이 byte [string+1]을 하게 되면 string이라는 메모리 주소에 +1을

하게 되는데 처음에 메모리 주소에서 포인터가 시작 주소를 가르키고 있었다고 한다면 

이렇게 되면 두번째 문자의 인덱스 위치로 포인터가 옮겨가게 된다.. )


* 여기서 주의할점은 만약 double word(4byte) 크기의 메모리였다면 

다음 인덱스로 옮겨가기 위해서는 +1이 아닌 +4를 해줘야 한다는 점이다!!!



( 위에서 주의하고 했던 점인데 buffer 메모리의 크기는 dword이기 때문에 

3번째 값을 가져오려고 한다면 +8( 4byte + 4byte )을 해줘야한다 )





2.  lea


  - 유효주소를 계산하는 명령어

  - lea dst, src

  - 특정 배열에 접근하려고 할때 많이 사용한다.

      * Load Effective Address로 mov를 사용할때와 마찬가지로 [ ] 안에서는 +, - 등과 같은 연산자를 사용 가능하다.




( lea 명령어는 유효주소를 계산하고 그 주소값을 레지스터나 메모리에 넣기만 할뿐 

mov 명령어처럼 그 메모리에 대한 값을 읽어오거나 하지는 않는다 )


* [ ] 안에 계산된 값은 주소값이므로 상수이다. 그러므로 앞에 크기를 붙여주지 않아도 된다.



( [buffer+2*4]에 대한 주소값 자체를 eax 레지스터에 넣어줬기 때문에 

buffer의 세번째 인덱스에 메모리 주소가 출력되는걸 볼 수 있다.. )



( 어셈블리에서는 add 명령을 쓰기위해 그전에 두 개의 명령어를 더 써야하므로

lea를 이용해서 연산을 하는 방법을 쓰기도 한다 )










반응형

댓글