명령어( 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를 이용해서 연산을 하는 방법을 쓰기도 한다 )
댓글