티스토리 뷰

C언어

C 언어로 내부 데이터 메모리 살펴보기

시작이반입니다 2021. 7. 28. 18:00

C 언어로 내부 데이터 메모리 살펴보기

이번 강좌에서는 같은 기능을 C 언어로 표현하는 방법을 공부하겠습니다. 프로그램 소스는 아래와 같습니다. 먼저 프로젝트를 만들고(c01.prj) 소스 프로그램을 입력 합니다.(c01.c) Make all 을 실행해서 에러가 없음을 확인하고, 디버그 메뉴의 Start 버튼을 눌러 아래 그림과 같이 표시되도록 만듭니다. #include // -- 1 #define IDATA ((char *)0x10000) // -- 2 void delay(long int dly) { while(dly--); } void disp(char ch) { P1 = ch; delay(10000); } void main() { char r0; // -- 3 char acc; // -- 4 r0 = 0x30; // -- 5 acc = 0x3a; // -- 6 IDATA[r0] = acc; // -- 7 disp(~IDATA[r0]); // -- 8 r0++; // -- 9 acc = acc + 2; // -- 10 IDATA[r0] = acc; disp(~IDATA[r0]); r0++; acc = acc + r0; IDATA[r0] = acc; disp(~IDATA[r0]); disp(0xff); // -- 11 r0++; acc = acc + IDATA[r0]; // -- 12 IDATA[r0] = acc; disp(~IDATA[r0]); r0++; acc = IDATA[0x33]; acc--; // -- 13 IDATA[r0] = acc; disp(~IDATA[r0]); } -- 1 : reg52.h 파일을 포함시키라는 명령입니다. reg52.h 에는 포트 이름과SFR 에서 정의된 레지스터 이름 등이 선언되어 있습니다. C 언어에서 같은 이름으로 사용할 수 있습니다. -- 2 : IDATA 를 ((char *) 0x10000) 이로 정의 한 것입니다. 0000 은 숫자이고 이것을 메모리를 가리키는 포인터로 형 변환 시키는 것이 (char *) 입니다. 이것을 캐스트(cast) 연산자라고 합니다. 0000 앞에 있는 1 은 이 포인터가 내부 데이터 메모리를 가리킨다는 것을 정의 한 것입니다. (외부 데이터를 가리키는 포인터로 정의 하려면 2 를 붙이고 코드(프로그램) 영역을 가리키는 포인터를 가리키려면 5 를 붙이면 됩니다.) -- 3 : 캐릭터 변수 r0 를 선언한 것입니다. 어셈에서 샤용하는 범용 레지스터 r0 와는 다른 것입니다. -- 4 : 캐릭터 변수 acc 를 선언한 것입니다. 어셈에서 사용하는 A 레지스터(ACC) 와는 다른 것입니다. 위와 같이 선언된 변수는 내부 메모리에 할당되며 내부 데이터 메모리 0x08 번지부터 할당됩니다. -- 5 : 변수 r0 에 16진수 30 (0x30) 을 입력하였습니다. [F8] 을 쳐서 스텝동작으로 보면 내부 데이터 메모리 0x08 번지에 30 값이 입력된 것을 볼 수 있습니다. -- 6 : 변수 acc 에 16진수 3a (0x3a) 을 입력하였습니다. [F8] 을 쳐서 스텝동작으로 보면 내부 메모리 0x09 번지에 3a 값이 입력된 것을 볼 수 있습니다. -- 7 : IDATA[r0] = acc; 이 명령은, 내부 데이터 메모리를 하나의 배열로 보고, IDATA[0x30] 에 acc 의 값, 즉 0x3a 를 입력하라는 것입니다. [F8] 을 쳐서 스텝동작으로 보면 내부 데이터 메모리 30 번지에 데이터(0x3a) 가 입력되는 것을 볼 수 있습니다. 0 번지가 30 으로 바뀐것은 컴파일러가 내부 데이터 메모리 포인터로 r0 (=00 번지) 를 사용하였기 때문입니다. -- 8 : disp(char ch) 함수는 매개 변수로 받은 ch 를 포트 1(P1) 에 출력하고 delay() 함수로 시간 지연을 시키는 기능을 합니다. disp(~IDATA[r0]) 에서 IDATA[r0] 는 30 번지에 있는 내용, 즉 3a 가 되고, "~" 는 비트 NOT 을 의미합니다. 포트 1의 LED는 부 논리로 되어 있기 때문에 값을 반전하여 출력 하였습니다. -- 9 : r0++ 는 변수 r0 의 값을 하나 증가시키는 명령입니다. r0 의 값은 0x08 번지에 있고 그 값은 30 이므로 하나 증가시키면 31 이 됩니다. [F8] 을 쳐서 확인 하세요. -- 10 : acc = acc + 2; 명령은 줄여서 acc += 2; 라고 쓸 수도 있으며, 변수 acc 의 내용에 2 를 더하라는 뜻입니다. 0x09 번지의 내용이 3c 가 됩니다. -- 11 : disp(0xFF) 명령은 다음 번의 LED 값이 이전 값과 같기 때문에 확인을 위하여 첨가 하였습니다. -- 12 : acc = acc + IDATA[r0]; 를 어셈으로 표현하면, add a,@r0 입니다. -- 13 : 변수 acc의 내용을 하나 감소하라는 명령입니다. 각 단계마다 [F8] 을 쳐서 스텝동작으로 명령이 실행되고, 변수값이 변화하는 것을 살펴 보았습니다. 이번에는 베타 키트에서 동작하는 것을 확인하겠습니다. 자료실에서 ISP 프로그램을 다운 받아 설치합니다.(EngineISP 가 ver 2.5 로 업 되었습니다.) ISP 케이블을 연결하고, ISP 프로그램을 실행합니다. ISP 프로그램의 열기 버튼을 눌러 c01.hex 파일을 엽니다. WRITE 버튼을 눌러 프로그램을 쓰면, 바로 실행이 됩니다. LED 의 변화가 빠르면 다시 RIDE51 에서 disp() 함수의 delay(100000); 함수 값을 증가 시키세요.

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2025/05   »
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 31
글 보관함