임시 데이터를 보관하는 스택

스택은 임시 데이터를 보관하는 메모리 공간입니다. 다시 말씀드립니다. 임시 데이터를 보관하는 메모리입니다. 절대 오래동안 쓸 데이터를 보관할 메모리가 아닙니다. 오래동안 여기저기서 사용할 데이터는 변수에 저장해야합니다. 스택은 잠깐 사용할 데이터를 저장합니다.

스택을 알게되면 어셈블리 프로그래밍을 위해 필요한 명령어는 다 배운게 됩니다. 그만큼 조금 어렵기도 하고 복잡하게 사용할 수도 있으므로 나름대로 많이 실험해보시기 바랍니다.

스택을 사용하는 명령어는 push와 pop입니다. push는 스택에 16비트 값을 저장합니다. pop은 스택에서 16비트 값을 읽어옵니다.

push의 사용법을 보면 레지스터 이름이 와도 되고 메모리 주소나 상수 값이 와도 됩니다. 레지스터의 값이나 메모리에 있는 값을 스택에 저장합니다.

push ax

push ds

push [bx]

pop 명령에는 레지스터와 메모리가 사용됩니다. 스택에서 값을 읽어서 레지스터나 메모리에 저장합니다.

pop ax

pop ds

pop [bx]

어렵지 않아 보이지요? 이제 진짜 스택이 뭔지 알아봅시다.

스택 포인터

스택은 메모리 공간이라고 했습니다. 그런데 메모리 어디라고는 설명을 안했습니다. 메모리 몇번지에 데이터를 저장하는 걸까요? 스택에 데이터를 저장했는데 메모리 몇번지에 저장되었는지 알 수 없을까요?

스택은 메모리 공간을 가르키는 말이므로 당연히 어디서부터 어디까지가 스택으로 사용되는 공간인지를 알아야합니다. 보통은 운영체제가 프로그램에게 일정한 크기의 공간을 스택으로 사용하도록 지정해줍니다. 그리고 그 공간을 다 쓰면 더 이상은 메모리를 쓰지 못하게 막습니다. 하나의 프로그램이 무한정 메모리를 사용할 수 없으니까요.

스택 공간의 주소는 ss (스택 세그먼트 레지스터), sp (스택 포인터 레지스터) 로 가르칩니다. 변수의 메모리 주소는 ds:[si]나 ds:[bx] 등으로 가르친다고 말씀드렸습니다. 스택도 마찬가지로 세그먼트 레지스터와 포인터 레지스터로 메모리 주소를 표현하지만 스택 전용의 레지스터가 따로 있다는게 다릅니다. 그만큼 자주 사용되니까 따로 레지스터를 만들어 둔 것이겠지요. 운영체제는 프로그램이 실행될 때 ss:sp를 설정해줍니다. 그리고 프로그램은 운영체제가 지정해준 메모리 위치를 스택으로 사용합니다.

push 명령이 스택에 데이터를 저장한다고 말씀드렸지요. 좀더 세부적으로 말씀드리면

  1. sp 레지스터에서 2를 뺀다(16비트이므로 하나의 데이터가 2바이트입니다. 그래서 2를 뺍니다)
  2. 저장할 데이터를 ss:[sp] 주소에 기록한다.

pop 명령은 반대로 동작합니다.

  1. ss:[sp] 주소에서 데이터를 읽어온다.
  2. sp 레지스터에 2를 더한다.

보통 데이터는 메모리 주소가 작은 지점에 저장하고 메모리 주소가 큰 쪽으로 데이터를 저장합니다. 100h에 문자열 "hello"를 저장한다면 h를 100h에 저장하고 e를 101h에 l를 102h에 저장합니다. 메모리 번지가 커지면서 다음 데이터가 저장됩니다.

하지만 스택은 반대입니다. 스택을 사용하기위해 push를 할 때마다 sp의 값이 줄어듭니다. 다음 데이터의 메모리 주소가 작아집니다. 스택 레지스터 sp의 값이 0fffeh이라면 처음 데이터를 저장할 때 먼저 sp 값을 0fffch로 감소시킵니다. 그리고 [0fffch]에 데이터를 저장합니다. 에물레이터를 실행하고 stack 버튼을 누르시면 스택의 상태를 확인할 수 있습니다.

스택의 주소값이 작아진다는 이유때문에 저장한 데이터가 거꾸로 꺼내진다는 특징이 있습니다. 1,2,3,4,5를 저장한다면 5,4,3,2,1 순서로 데이터가 꺼내집니다. 스택이란 말의 원래 뜻이 접시를 쌓아놓는 것이라고 합니다. 가장 먼저 쌓아놓은 접시는 가장 나중에 꺼낼 수가 있습니다. 가장 나중에 쌓은 접시가 가장 위에 있으니까 가장 먼저 꺼내집니다.

다음 예제를 한번 실행해보겠습니다.

ORG    100h


mov ax, 1234h
push ax
push ax
pop bx
pop dx

ret

다음은 에물레이터의 실행 결과입니다.

에물레이터를 처음 실행해서 stack 버튼을 누릅니다. 그러면 ss:sp 주소에 맞게 700h:0fffeh 번지의 메모리에 어떤 값들이 있는지 나타납니다. 처음에는 모두 0입니다. push ax를 실행하면 0fffch에 1234h가 저장되고 그 다음 push ax를 실행하면 0fffah에 1234h가 저장됩니다. 처음 프로그램이 실행될때의 sp 값은 0fffeh인데 0fffeh에는 데이터가 저장되지 않습니다.

그리고 pop bx를 실행하면 sp 값이 0fffah에서 0fffch가 되면서 bx에 스택에 있는 값 1234h가 저장됩니다. pop dx도 마찬가지입니다.

메모리에 있는 값들을 레지스터로 복사했지만 메모리의 값을 바꾸지는 않았으므로 메모리값들은 그대로 남아있습니다. 이렇게 스택에 값이 남아있기때문에 해커들이 스택의 값을 읽어서 해킹에 사용하는 일이 있었습니다.

results matching ""

    No results matching ""