티스토리 뷰

안녕하세요!

 

이번 시간에는 mov 명령어에 대해서 알아보고 직접 mov 명령어를 사용해서 어셈블리 프로그래밍을 해볼거에요.

 

지난 시간에는 gdb를 사용하여 막 짜본 프로그램을 분석을 해보았는데요, 우리가 짠 프로그램의 문제점이 무엇이었는지 기억하시나요??

 

네, 프로그램의 문제점은 프로그램의 종료를 알리는 신호를 주지 못해서 Segmentation fault가 발생한다는 점이었습니다.

 

프로그램의 끝은 시스템 콜을 이용해야 하는데요, 이번 시간에는 시스템 콜을 이용하여 프로그램을 정상적으로 종료시키는 방법도 알아보겠습니다.

 

자 그럼 MOV 명령어는 무엇이냐!!?

 

MOV : 데이터 복사를 담당하는 명령어

# 레지스터 -> 레지스터 (레지스터에서 레지스터로 데이터를 복사)

# 메모리 <-> 레지스터 (메모리에서 레지스터로, 레지스터에서 메모리로 데이터를 복사)

# Immediate(상수) -> 레지스터 or 메모리 ( 상수를 레지스터로, 상수를 메모리로 데이터를 복사)

# Memory to Memory불가능하다!! (메모리에서 메모리로 데이터를 복사하는 행위는 불가능하다.)

 

MOV에 대해서 감이 오시나요??

 

이해가 되지 않으신다면 직접 프로그램을 짜서 분석을 해볼게요.

 

 

mov    eax, ebx                (ebx의 값을 eax에 넣는다) <백업의 역할>

 

mov    ebx, 0xbffff098        (0xbffff098을 ebx에 넣는다)

 

mov    dword [ebx], 0x10    (대괄호의 의미는 포인터의 의미와 동일, ebx의 값이 가리키는 메모리 주소에 0x10을 넣는다)

 

mov    ebx, eax                (eax의 값을 ebx에 넣는다) <백업의 역할>

0xbffff098가 무엇을 의미하는지 궁금한 분들이 계실거에요, 일단은 그냥 넘어가봅시다!

 

작성한 이 코드를 컴파일 및 링크를 진행해주시고 gdb로 열어볼게요.

 

(gdb의 q 옵션은 불필요한 출력을 없애주는 역할을 합니다)

 

main을 disas 해보면 위와 같이 출력이 되는데요,

 

main의 시작지점에서 9의 offset 만큼 떨어진 지점에 break point를 걸어주고 ni 명령어를 통해 명령어를 하나씩 실행시키면서 변화를 확인해볼게요.

 

 

push 와 pop이 모두 실행되어서 eax, ebx에 각각 값이 들어가 있는 것을 확인할 수 있습니다.

 

지금부터 ni 명령어를 사용하여 명령어를 하나씩 실행시키면서 어떻게 변화하는지 확인해보겠습니다.

 

 

ebx에 저장되어 있던 0x10이 mov명령어가 실행되고 나서 eax로 데이터가 복사되었음을 확인할 수 있었습니다.

 

 

ebx에 저장되어있던 0x10이 mov 명령어가 실행되고 나서 0xbffff098로 값이 덮어쓰여진 것을 확인할 수 있습니다.

 

 

앞서 설명드렸듯이 대괄호는 포인터와 의미가 비슷하다고 설명드렸습니다.

 

이 시점에서 ebx에는 0xbffff098이 저장되어 있고, 0xbffff098이 가리키는 메모리 공간에 0x10을 복사하라는 mov 명령어를 실행하고 나서 메모리 0xbffff098의 값을 확인해보니 0x10이 복사되어 있음을 확인할 수 있습니다.

 

이제 mov 명령어에 대해서 조금 감이 오시나요??

 

 

이 프로그램은 지난 시간과 동일하게 Segmentation fault가 발생합니다.

 

그 이유는 프로그램을 정상적으로 끝맺음을 하지 않았기 때문입니다.

 

지금부터는 시스템 콜을 이용하여 프로그램을 정상적으로 종료하는 방법을 알아보겠습니다.

 

 

코드의 마지막에 파란 선으로 표시한 코드를 작성하시면 됩니다.

 

mov    eax, 1        ( eax에 넣은 것은 함수 코드번호)

mov    ebx, 0        ( ebx에 0을 넣은 것은 정상종료임을 의미)

int    80h            ( 시스템 콜 )

 

c언어의 exit(0)과 동일한 의미입니다.

 

간단한 예제를 통해 프로그램을 정상적으로 종료시키는 방법을 알아보았습니다.

 

시스템 콜에 대해서 궁금한 점이 있으시다면 인터넷에 'linux system call'로 검색을 해보시기 바랍니다.

 

이제 우리는 스택에 데이터를 넣거나 뺄 수 있으며, 값을 이리저리 옮길 수 있고, 프로그램을 종료시킬 수 있습니다.

 

아직은 프로그램의 규모가 작지만 공부를 하면서 점차적으로 큰 어셈블리 프로그램을 만들어보도록 하겠습니다.

 

다음시간에는 add 명령어와, sub 명령어에 대해서 알아보겠습니다!

 

 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함