본문 바로가기
프로그래밍

프로그래밍에서 주소(Addresses)와 데이터(Data)는 어떻게 다른가?

by bantomak 2023. 8. 8.
반응형

주소(Address)와 데이터(Data)

주소와 데이터는 컴퓨터 공학에서 가장 일반적인 두 단어이다. 데이터는 정보(information)를 설명하는 용어이고 주소는 정보의 위치(location)를 설명하는 용어이다. 이는 매우 간단하고 명확하게 들린다. 그러나 이는 생각보다 간단한 이야기는 아니다. 그렇다면 왜 주소와 데이터는 개념은 이해하기 어려울까? 예를 들어 나는 Alan Clements이고  Merrington Avenue 12에 산다. 누군가 내 주소를 헷갈려할까?  현실세계(non-computer world)에서 이 구분은 명확하다. 그러나 컴퓨터 세상에서 주소와 데이터는 다소 미묘하다.

 

주소와 데이터를 이용하여 C언어로 표현된 요소들을 생각해 보자.

 

int t, *b;

int a[10];

b = &a[3];

t = *b;

 

연산자 *와 &은 주소를 다루기 위해서 사용된다. 이 경우에는 주소와 데이터 간의 구별이 초보자들에게  즉각적으로 명확하지 않다. 아래와 같은 저 레벨의 언어로 이루어진 경우를 생각해 보자

 

LDR r1, [r1]

MOVE (A1), A1

 

두 명령어 모두 같은 행동을 실행한다. 둘 다 포인터를 데이터로 받아서 다시 한번 포인터를 데이터로 대체한다. 이러한 실행은 데이터와 주소의 개념에 연관되어 있다. 이런 실행의 의미는 해당 개념들을 처음 접하는 사람에게는 명확하지 않을 것이다.

 

데이터(Data)

데이터를 정의하는 것은 어렵다. 여러 사람들에 의해 다른 방식으로 사용되기 때문이다. 컴퓨터 공학에서 데이터는 주로 이진 형태로 컴퓨터 안에 저장되어 있는 정보를 의미한다. 정보는 아마 단일 요소(예를 들어 숫자 혹은 알파벳 글자)나 요소들의 집합(예를 들어 array, list, string 또는 table)으로 구성일 것이다.

 

데이터의 타입은 주로 integer, real(floating-point), 또는 character로 제한되어서 표현된다. 이러한 제한들은 컴퓨터 명령어 수행으로 간단하게 사용된다.

 

주소(Address)

컴퓨터 공학에서 주소는 메모리 상의 데이터 위치를 표현하는 데 사용된다. 컴퓨터 메모리 상의 아주 큰 저장 요소들의 배열로 간주된다. 각각의 이러한 메모리 저장소들은 데이터를 저장한다. 0x12345678에 interger 값 0x57이 저장된다고 말할 수 있다. (0x를 앞에 붙인 것은 주소와 데이터를 16진수로 표현하기 위해서이다.)

 

x = x + 1

x의 데이터 값을 1 증가시키려고 한다.

이는 간단해 보이지만 생각하는 것처럼 그리 간단한 일은 아니다. 첫째로 우리가 고등학교에서 배웠던 대수학의 규칙을 지키고 있지 않다. x = x + 1 표현식은 방정식처럼 보이지만 방정식이 아니다.

 

사실 우리는 이렇게 표현해야 한다.

x  x + 1

왼쪽 값을 표시하기 위해서 오른쪽 값은 대체되어야 한다. 몇몇 언어들에서 이를 수행하기 위해서 = 와 같은 특별한 심벌을 사용하여 데이터의 전달을 표시한다. 다른 문제도 있다. x란 대체 무엇인가? 이는 address/data 구분에 혼란을 주는 핵심이다. 우리가 x를 작성하면 이는 메모리 어딘가에 저장된 데이터 값을 가리키는 것으로 사용한다. 그러므로 x는 진정으로 데이터의 주소이다. 우리가 방정식 안에 있는 x를 보면 자동으로 x의 주소가 아니라 x의 값에 대해서 생각하게 된다. 우리는 잠재의식의 레벨에서 아무 생각 없이 주소 x를 이에 상응하는 데이터로 자동변환하여 생각한다. 불행하게도 프로그램을 작성할 때 우리는 x의 주소와 x의 주소에 저장된 데이터를 구별해야 한다.

 

메모리, 데이터 그리고 C

메모리 상에 데이터가 어떻게 저장되지 보도록 하자. 그리고 C언어가 어떻게 주소와 데이터를 표현하는지 보자. 아래의 그림에서 실제 숫자 형식의 주소와 데이터를 가진 메모리 맵을 그리고 있다. 일반적으로 아무도 이런 숫자 형식의 데이터를 가지고 일하지 않는다. 왜냐면 우리는 데이터가 메모리 상에 어디에 있는지 전혀 신경 쓰지 않는다. 오직 컴퓨터 구조설계자들만이 이러한 레벨에 관심을 갖는다. 왜냐면 그들은 컴퓨터 시스템을 디자인하기 때문이다.

 

우리는 32-bit 단위의 4바이트로 가정하겠다. 연속적인 메모리 단위는 4바이트 단위로 나눠진다. 0000, 0004, 0008, 000C, 0010, 0014로 이어진다. 기억하자. 주소들은 16진수 형태를 갖는다. 

 

예를 들어 메모리 위치 0x1204는 0x27의 데이터를 가진다. 숫자 값인 0x1204는 데이터의 주소이다. 숫자 값은 0x27은 실제 데이터이다. 우리는 q 주소의 데이터 값은 p인걸 p = [q]로 표시할 수 있다. []은 "포함하고 있는 내용물"로 읽힌다. 그래서 p = [q]는 "p는 메모리 위치 q의 내용물이다."라고 말할 수 있다. 

 

1

 

다음 그림은 변수의 위치를 표현하기 위해서 상징적 이름(Symbolic name) X을 사용했다는 걸 제외하고는 동일한 그림이다. 여기서 궁금증이 발생할 것이다. 만약 X의 값이 무엇인지 묻는다면 우리는 두 가지로 대답할 수 있다. 만약 "X가 표현하고 있는 주소가 뭐냐"라고 묻는다면 답은 0x1204이다. 만약 "X가 표현하고 있는 주소의 데이터가 뭐냐"라고 묻는 거라면 답은 0x27이다.

 

이러한 두 가지 개념을 대수적으로 표현하자면 X = 0x1204 (X는 0x1204의 주소) 혹은 0x27 = [X] (X 안에 저장되어 있는 데이터는 0x27)

 

2

 

C는 고수준의 언어이며. 이는 주소와 데이터를 명확하게 구분한다. 게다가 C는 고수준 어셈블리 언어라고도 불린다. 다음 그림은 C에서 * 연산자를 이용해서 주어진 주소값의 데이터 값을 어떻게 반환하는지 보여준다.

 

3

 

만약 X가 주소라면 *X는 해당 주소의 내용물을 말한다. 다른 말로, * 연산자는 RTL(register tranfer language)의 []와 사용법과 동일하다. 다음의 그림은 C의 & 연사자를 나타낸다. *의 정반대의 기능을 한다고 생각하면 편하다. & 연사자는 변수의 주소를 반환한다. X가 변수라고 한다면 &X는 변수의 주소를 나타낸다.

 

X란 메모리의 주소값을 추상화한 개념이다.

 

4

 

ARM 어셈블리 언어에서 주소와 데이터

몇몇 특별한 블록 이동 명령어를 제외하면, ARM은 메모리에 접근하기 위한 오직 2가지 명령어만을 제공한다.

  • 메모리에서 데이터 불러와서 레지스터에 로드하기 명령어(LDR)
  • 레지스터에서 데이터를 불러와서 메모리 어딘가에 저장하기

레지스터 로드 명령어는 LDR은 LDR r1, 0x012345678 명령어를 보면 예상 가능하듯이 메모리 위치 0x12345678의 내용물을 r1 레지스터에 복사한다. ARM 명령어는 간단하지 않다. 그 이유는 메모리 주소를 위한 op-code 공간이 존재하지 않기 때문이다.

 

따라서 ARM의 로드 명령어는 특정 실제 주소를 항으로 가지는 대신에  LDR r1, [r2]와 같은 형태를 가진다. 이 경우에 r2 레지스터의 내용물은 주소가 된다. 

 

[r1] <-  [[r2]]

 

이 표현은 다음과 같이 읽힌다. 주소가 r2 레지스터에 내용물로 특정된 주소의 메모리 위치에 내용물을 r1 레지스터에 로드하라. 이를 그림으로 표현하면 이렇게 표현이 가능하다.

포인터 레지스터 r2는 주소를 포함하고 있다. X라고 불리는 변수는 그 주소가 0x1204이다. 메모리 위치 0x1204의 데이터는 0x57이다. 만약 우리가 LDR r1, [r2]를 실행하면 우리는 r1 레지스터에 0x1204가 아니라 값 0x57을 로드하게 된다. 

 

X = X + 1로 돌아와서

위 작업을 수행하기 위해서 우리는 이렇게 작성할 수 있다.

 

LDR r1,[r2]     ;  r1 레지스터에 X를 불러온다.

ADD r1,r1,#1    ; X + 1을 구해서 X에 추가한다.

STR r1,[r2]     ; 메모리상의 X에 저장한다.

 

기계 수준의 코드는 우리에게 주소와 데이터를 이해하기를 요구한다. 반면에 어떻게 작동하는지 설명으로 추가된 코멘트는 구분이 덜 명확하다.

 

r1 레지스터 안의 주소 X가 들어가는지 우린 언급하지 않았다. 메모리 위치 0x1234 안에 X의 데이터 값이 들어가는지도 말이다. 상상해 보자 위에 표시된 코드 전에 아마도 우리는 이런 코드를 실행했을 것이다.

 

MOV r0,#0x57    ; r0 레지스터에 실제 값을 로드한다.

MOV r2,#0x1204  ; r2 레지스터에 X의 주소를 로드한다.

STR r0,[r2]     ; 메모리에 저장한다.

 

이제 메모리에 X의 값을 그리고 r2 레지스트에 X의 주소를 설정했다.

 

상징적 이름(Symbolic name) 사용

실제 프로그램에서 실제 주소들에 대해서 걱정할 필요가 없다.

 

AREA Demo, CODE, READWRITE

     ENTRY

     ADR r2,X        ; r2 레지스터가 X를 가리키도록 설정

     MOV r0,#0x57    ;r0 레지스터에 값 설정

     STR r0,[r2]     ; X에 값 설정

 

     LDR r1,[r2]     ; r1 레지스터에 X의 값을 로드

     ADD r1,r1,#1    ; X에 X + 1을 더해준다.

     STR r1,[r2]     ; 결과값을 X에 저장

     END

 

함께 읽으면 좋은 글

 

Chapter 2: ARM Assembly 기초

작업에 들어가기 전에 ARM Assembly에 대해 배워보도록 합시다. ARM CPU의 기본 구성 R0 ~ R14 총 15개의 범용 레지스터를 가지고 있습니다. 범용 레지스터 R13 는 특수 레지스터 SP 로 사용됩니다. SP 는 C

kyuhyuk.kr

출처

 

Addresses and Data

Addresses and Data Two of the most common terms in computer science are address and data. Data is the term used to describe information, and address is the term used to describe the location of an item of information.  It all sounds very simple and obviou

alanclements.org

댓글