IT/C_C++_Assembly2011. 12. 20. 18:10

  

이번글에서는 레지스터의 종류와 스택에 대해서 알아보도록 하겠습니다.

레지스터는 CPU내부의 대표적인 저장장치입니다. 레지스터는 CPU의 설계에 따라,또는 사용하는 용도와 목적에 따라 종류가 다양합니다. 이외에 스택이라는 저장장치가 있는데 일반적인 저장장치와 다르게 주소를 지정하는 방법과 읽고 쓰는 방법이 간단하다는 특징이 있습니다.

 
[표] 레지스터의 이름과 종류 

  

약 어

 

Accumulator(어큐뮬레이터)

Base Register(베이스 레지스터)

Count Register(카운트 레지스터)

Data Register(데이터 레지스터)

Base Pointer(베이스 포인터)

Instruction Pointer(인스트럭션 포인터)

Stack Pointer(스택 포인터)

Destination index

Source Index(소스 인덱스)

Data Segment Register(데이터 세그먼트 레지스터)

Extra Segment Register(엑스트라 세그먼트 레지스터)

Stack Segment Register(스택 세그먼트 레지스터)

Code Segment Register(코드 세그먼트 레지스터)

Flags Register(플래그 레지스터)

EAX

EBX

ECX

EDX

EBP

EIP

ESP

EDI

ESI

DS

ES

SS

CS

none

범용 레지스터

범용 레지스터

범용 레지스터

범용 레지스터

오프셋 레지스터

오프셋 레지스터

오프셋 레지스터

오프셋 레지스터

오프셋 레지스터

세그먼트 레지스터

세그먼트 레지스터

세그먼트 레지스터

세그먼트 레지스터

none

 

. EAX연산 결과를 저장하는 용도로 사용될 뿐만 아니라 데이터의 이동과 데이터의 일시적 저장 등 범용 레지스터의 기능을 담당.

. EBX데이터의 이동, 일시적 저장 등 범용 레지스터의 기능을 갖는다. 또한 간접 번지 지정에 사용. 베이스를 지정해 주는 레지스터

. ECX데이터의 이동, 일시적 저장 등 범용 레지스터의 기능을 갖는다. 반복적인 데이터의 연산, 논리 명령 등에 많이 사용.

. EDX데이터의 이동, 일시적 저장 등 범용 레지스터의 기능을 갖는다. 곱셈과 나눗셈에서 AX 레지스터의 범위를 초과할 경우에 많이 사용.

. ESI소스 색인을 위한 레지스터.

. EDI – ES(엑스트라 세그먼트 레지스터)와 조합을 이루어 사용되고 그 외에 연산에도 활용이 가능합니다. EDI역시 ESI와 같이 간접 주소 지정 방식에 많이 사용.

. EIP명령 포인터(Instruction Pointer)의 약자로서, 이 레지스터는 실행할 다음 명령의 번지를 가르키는데 사용됩니다.

. EBP레지스터는 스택에서 데이터를 다루기 위해 사용되는 레지스터. EBP레지스터는 스택 내에서 상대 주소 값(변위 또는 오프셋)을 저장하는데 많이 사용됩니다.

. ESP – SP(Stack Pointer) 스택 내의 포인터를 설정하기 위한 레지스터.

. 플래그 레지스터 플래그란 컴퓨터에서의 연산결과에 대한 정보를 얻기 위해서 마련한 표시판입니다. 플래그 레지스터에는 처리 결과(상태)에 대한 16가지 정보를 표시하는 비트가 있습니다. 즉 플래그 레지스터는 2바이트의 레지스터로 각 비트는 해당 연산 결과에 대한 정보 또는 상태를 보여줍니다.

 

그리고 스택에 대해 알아볼까요?

스택(Stack) CPU내부의 레지스터 집합에 존재하는 저장장치입니다. 레지스터와는 다른 특징이 있습니다. 우선 데이터가 순차적으로 저장되며, 요소의 개수와 스택의 길이는 가변적입니다. 그리고 한번에 하나의 요소에만 액세스가 가능합니다. 결과적으로 데이터 접근 방법은 나중 입력 먼저 출력(LIFO)의 특징을 갖습니다.

 

PUSH & POP

스택의 동작에서 데이터가 입력되고 출력되는 부분을 스택의 TOP이라고 합니다.

PUSH : 스택의 TOP에 새로운 요소를 추가 저장하는 동작을 PUSH라고 합니다.

POP  : 스택의 TOP에서 하나의 요소를 꺼내는 동작을 POP이라고 합니다.

Posted by 예영교육 연구소
IT/C_C++_Assembly2011. 12. 20. 14:59

이 글을 쓰는 이유는 어셈블러를 학습하기 전에 컴퓨터에 대한 기본적인 지식을 쌓기 위함입니다.

짧은 글로서 방대한 내용을 다 표현하기 보다 어셈블러를 학습하기 위한 기초적인 이해를 쌓는 것이 저의 가장 큰 목표입니다.

이 글에서 다룰 내용은 다음과 같습니다.

가.   컴퓨터 구조에 대해 이해합니다.

나.   CPU에 대해서 기본적인 이해를 합니다.

 


함께 그럼 가 보겠습니다.

컴퓨터는 무엇으로 구성되어 있을까요?



다음과 같이 하드웨어 + 소프트웨어로 구성되어 있습니다.

그럼 하드웨어의 소프트웨어는 이해는 가시지만 하드웨어에 대해서 간단하게 설명하고 넘어가겠습니다.

 

중앙처리장치(CPU) : 컴퓨터 시스템 전체를 제어하는 장치로서 입력장치에서 입력받은 데이터를 처리한 후 출력장치와 기억장치로 보내는 과정을 수행합니다.

기억장치 : 필요한 데이터를 저장하기 위해 기억장치를 이용합니다. 주기억장치로는 현재 RAM를 이용합니다. 보조기억장치로는 하드디스크, 플로피 디스크, CD-ROM등을 이용합니다.

입출력장치 : 컴퓨터에서 처리할 데이터를 외부에서 입력 받을 수 있게 해 줍니다.(입력장치), 컴퓨터 내부에서 처리된 데이터를 사용자가 보거나 할 수 있도록 출력매체를 이용해서 보냅니다. 마우스, 키보드, 스캐너, 모니터, 스피커 등이 여기에 해당됩니다.

 

자 그럼 여기까지는 문제없이 이해하셨죠.

 

자 그럼 이제 핵심이 되는 CPU에 대한 기초 지식을 쌓아보겠습니다.

CPU종류 : 속도를 더 높이기 위해 하나의 기판에 CPU 1(싱글), 듀얼(2), 쿼드(4)를 구현하고 있습니다. 최근에는 8개가지 하나의 기판 위에 구현하여 속도를 높이고 있습니다.(참고로 쿼드는 인텔과 AMD가 차이가 있습니다. 그리고 AMD에는 CPU 3,6,8개를 구현한 제품도 있습니다.)

쉽게 설명하면 일을 할 때 사람을 한 명을 둔 것을 2,3,…, 여러명으로 늘린 것으로 생각하면 되겠네요. 그만큼 속도는 빨리지겠죠.

 

컴퓨터 구조를 이해하기 쉽게 여러 권을 참고해서 그림을 그려보았습니다. 혹시 잘못된 부분이 있다면 과감한 지적을 부탁드리며 참고해 주세요.


CPU 내부에는 ALU(산술 논리연산장치), 제어장치, 레지스터로 구성됩니다. 그리고 CPU와 주기억장치(RAM), 기타 I/O장치는 Bus라 불리는 것에 의해 연결됩니다. 더 자세히 들어가면 좀 복잡해 질 듯 해서 여기까지 마무리짓겠습니다.

우리가 여기서 어셈블리어를 통해 다룰 부분은 CPU의 레지스터를 많이 다룰 것 같습니다. 이런 형식으로 컴퓨터가 되어 있다고 이해가 되면 다음 단계로 넘어가기가 수월해 지리라 믿습니다. 저는 처음에 어떻게 되는 건지 하나도 모르겠더라구요. 그래서 나름 학습하며 정리해 봅니다.

Posted by 예영교육 연구소
IT/C_C++_Assembly2011. 12. 19. 17:20
용어 간단 정리
BUS(버스)?
자료나 주소, 제어신호를 송수신하기 위한 병렬 전선
  DATA BUS : 자료나 프로그램을 송수신하는 버스
  Adderss Bus : 주소만을 송수신 하는 버스

Intel 80X86의 개요
Intel 8086 16비트의 프로세스. Intel 계열의 어셈블리어 8086부터 시작
Intel 8088
> 8086의 변형으로 등장. 외부적으로 8비트를 액세스
> IBM사는 8088에 기초하여 첫 세대 개인용 컴퓨터를 제작.

Intel 80286
16비트 프로세스지만 8086보다 빠르고 매우 중요한 기능을 상당수 보완.
중요 기능들
 (1) 동작 모드 : 실제주소모드 하에서 80286은 8086과 동일하게 동작하며, 8086의 프로그램도 수정하지 않은 채 실행될 수 있다. 보호가상주소모드는 보호모드라고도 불린다. 보호모드 하에서 80286은 다중작업(Multitasking)과 메모리보호(memory protection)기능을 지원

 (2) 확장된 메모리 주소 공간
  8086/8088에서는 1메가 바이트 한도의 메모리 공간 지원하지만, 80286은 보호모드 하에서 16메가바이트(22바이트)의 메모리 공간을 지원한다. 

 (3) 가상메모리(Virtual memory)
 가상 메모리란 실제의 RAM 또는 ROM 메모리공간을 초월하여 외부보조기억 장치의 공간까지 확대하여 실제의 메모리 공간처럼 이용할 수 있도록 한 기법

 (4) 80286은 8086/8088과 동일한 주소지정방식을 사용함. 기본적 명령군을 포함하기 때문에  8086/8088의 소프트웨어 그대로 수용

 동적 메모리 기능과 기가바이트의 가상주소공간을 이용하여 다수 사용자 시스템, 재 프로그램 기능, 실시간 처리, 실시간 다중처리 기법의 응용프로그램에 적용될 수 있다.

Intel 80386
32비트 마이크로 프로세서. 80286보다 훨씬 빠르다. 32비트의 내부 버스에 의해 프로그램이나 자료가 단위 시간당 더 많이 이동 가능하며, 클럭 사이클 33MHz로서 80286의 명령 처리 속도보다도 빠르다.

보호 모드하에서 80386은 4기가 바이트 실제 메모리 주소 이용. 보호모드 하에서 또한 가상메모리 기능을 발휘 이 경우에는 64테라바이트의 가상 메모리 주소공간을 이용 가능.

Intel 80486
1989년에 발표. 32비트 마이크로프로세서. 80486은 80386기능과 실수 연산 보조 프로세서인 80387등의 기능을 총집합 시킨 것이다. 80486은 8킬로바이트의 캐시메모리를 포함하고 있어서 더 빠른 자료조작을 할 수 있다.캐시 메모리란 메모리보다 더 빠르지만 레지스터는 아니다.

 
Posted by 예영교육 연구소
IT/C_C++_Assembly2011. 12. 16. 14:40

 

보안 분야로 준비를 하면서 수업시간의 내용을 개인적으로 내용을 정리해 보겠습니다.
아래의 내용을 처음부터 하나 하나 공부해 가면 많은 내용 학습을 필요할 수도 있습니다. 
저는 이 글의 목표를 어셈블리어를 이용한 Hello World를 출력하는 것으로 목표로 합니다. 
상세한 내용을 담기에는 너무 글이 길어지고 저도 또한 시간상의 부족한 부분이 있기에 이해해 주시기를 바라며.... 

 
기본 지식

레지스터

레지스터를 간단히 말하면 컴퓨터의 프로세서(CPU, DSP, GPU)가 내부에 유지하는 적은 영역의 기억장치입니다. 대부분의 프로세서는메인 메모리에서 레지스터로 옮겨와 데이터를 처리한 후 그 내용을 다시 레지스터에서 메모리로 저장하는 로드-스토어설계를 사용하고 있습니다.

 

레지스터의 종류

레지스터는 용도에 따라 몇 가지 종류가 있다. 그 중에 몇가지를 간단히 알아보겠습니다.


데이터 레지스터 : 정수 값을 저장할 수 있는 레지스터

주소 레지스터 : 메모리 주소를 저장하여 메모리 접근에 사용되는 레지스터  

범용 레지스터 : 데이터와 주소를 모두 저장할 수 있는 레지스터

부동 소수점 레지스터: 부동소수점 값을 저장하기 위한 레지스터

상수 레지스터 : 0이나 1과같은 고정된 값을 저장하고 있는 레지스터

특수 레지스터 : 프로그램의 상태를 저장하는 레지스터, 프로그램 카운터, 스택 포인터, 상태레지스터 등이 있습니다.

 

포인터와 인덱스 레지스터

32비트 일반 주소 레지스터는 4개가있으며, 일반 레지스터에 속하지 않는 주소 레지스터 EIP도 있습니다.
세그먼트 내에서의 옵셋 값을 기억하며 메모리의 위치를 지적하는데 사용됩니다.
ESP(stack pointer) : 스택의 꼭대기 주소를 포함합니다.
EBP(base pointer) : 현재 스택 프레임의 주소를 담습니다. 주소 스택의 자료를 액세스하기 위해 사용됩니다.
ESI(source index) : 문자열 연산에서 사용되는 원본주소를 포함합니다.
EDI(destination index) : 문자열 연산에서 사용되는목적 주소를 포함합니다.
EIP(instruction pointer) : 현재 실행되는 명령의주소를 포함합니다.

 
세그먼트 레지스터
CS(Code Segment register)  : 명령어 코드를 기억시킨다.
DS(Data Segment register)   : 자료를 기억시킨다.
SS(Stack Segment register)  : 스택 영역으로 사용한다.
ES(Extra Segment register)   : 데이터 세그먼트를 한 가지 더 추가할 때 둘째 번 데이터 세그먼트

 

범용 레지스터란?

특수한 목적을 가지지 않은 명령에 의해 각종 기능을 수행하는 레지스터,

데이터를 계산하는 회로와 어드레스의 계산하는 회로를 함께 가지고 있고, 명령의종류를 줄이는것이 가능하므로 대부분의 프로세서가 가지고 있는 레지스터입니다. 프로그래밍의 자유도가 크게증가하고, 특별히 컴파일러 실행 효율이 좋으므로 오브젝트를 생성하는 것이 쉽습니다. RISC계 프로세서는 범용 레지스터가 동일한 기능을 가지고 있는 것이 많습니다.

EAX(Accumulator) : 워드 단위의 곱셈, 나눗셈, 입출력  
EBX(Base Register) : 주소의 기저, XLAT명령 등에 사용
ECX(Counte Register) : 스트링 조작, REP, Loop등에서 사용
EDX(Data Register) : 곱셈, 나눗셈 및 입출력 명령에 이용

간단한 레지스터의 역사(비트의 확장)
처음에는 우리는 8bit프로세서를 사용하다가 지금은 32bit, 64bit의 사용하고 있습니다.
레지스터도 명칭이 이에 따라 변경되어 왔습니다.


CPU

범용 레지스터

8bit CPU(8086)

“a”, “b”, “c”,"d"

확장 CPU(8086)

“ax”, “bx”, “cx”, "dx"

32bit CPU(80386)

“eax”, “ebx”, “ecx”, “edx” (e extend의 약자)

64bit AMD64

“rax”, “rbx”, “rcx”

 

실습

 

먼저 C언어를이용하여 hello world을 출력해 보겠습니다. 아래에서 이를 구현하는 어셈블리어를 작성하고 실행시켜 볼 것입니다.

 int main() {

  write(1, “hello world\n”,14);

  return 0;

} 

 

컴파일하고 출력해 보면 다음과 같습니다.
 





위의 것을 그대로 어셈블리어로 구현해 보겠습니다..

 .data

   hello :

    .string “hello world”

 

.globl main:

   main:

    mov $4, %eax

    mov $1, %ebx

    mov $hello, %ecx

    mov $14, %edx

    int $0x80

 

 

코드 설명

.data                                 // 영역을 지정합니다.

   hello :                            //  변수 선언

    .string “hello world\n”      //  변수에 문자열 “hello world\n” 넣기

 

.globl main:                       // main 함수 작성

   main:                             // main함수의 내용 적기

    mov $4, %eax               // eax레지스터에 4 넣기(write() 의미하는 System call no)

    mov $1, %ebx               // ebx레지스터에 1 넣기(Standard_out 의미)

    mov $hello, %ecx          // string(hello) 주소

    mov $14, %edx             // string size

    int $0x80                      // 인터럽트 수행

 
  write(1, “hello world\n”,14); 의 한줄은 어셈블리어에서는 다음으로 표현됩니다.
==========================================================================

    mov $4, %eax           // eax레지스터에 4 넣기(write() 의미하는 System call no)

    mov $1, %ebx           // ebx레지스터에 1 넣기(Standard_out 의미)

    mov $hello, %ecx      // string(hello) 주소

    mov $14, %edx         // string size

    int $0x80                  // 인터럽트 수행

 ==========================================================================

이를 컴파일 하고 다시 결과를 확인해 보겠습니다.

여기서 저장하는 파일의 확장명은 ‘[파일명].s’입니다그리고 컴파일 하는 방법은 C와 동일합니다.

 

# gcc [파일명].s

# ./a.out




자 다음과 같이 write()함수를 system call하여 문자를 출력했습니다하지만

자 여기서 한가지 에러가 발생했네요.

‘Segmentation fault’

이 에러는 자원을 릴리즈하는 별도의 루틴을 설정하지 않았기 때문이다이를 해결하기 위해 exit(0) 시스템 콜을 호출합니다다음의 행을 추가합니다.

 

이를 해결해 보도록 하겠습니다.

mov $1, %eax

mov $0, %ebx

int $0x80

이 코드의 의미는  ‘exit(0);’의 의미와 동일한 의미를 갖습니다.

 

자 그럼 코드를 추가한 후최종 결과를 확인해 볼까요~~~


 
 
정상적으로 실행이 확인되었습니다. 자 출력하는 것을 실습해 보았습니다. ^^

이론을 많이 보는 것보다 한번 해보는 것이 저는 이해가 빠른 것 같네요.

혹시라도 내용중에 추가나 수정해야할 부분이 있다면 지적을 부탁드립니다. 더 나은 지식 나눔을 추구합니다.
그러면 좋은 하루 되세요.

<위키 백과 참조>

 

 

 

 

 

 

 

 

Posted by 예영교육 연구소