8. 하드웨어의 프로시저 지원

2023. 4. 11. 19:38·컴퓨터 구조/Ch2. 명령어 : 컴퓨터 언어
Reference :
- 컴퓨터 구조 및 설계 MIPS EDITION [6판] / David A. Patterson / 한빛에듀
- 건국대학교 컴퓨터구조 강의 / 박능수 교수님
- https://developbear.tistory.com/ (김베어의 개발일지)
프로시저 (procedure)

프로시저(procedure)는 제공되는 인수(parameter)에 따라서 특정 작업을 수행하는 서브루틴을 말한다.

 

프로시저는 프로그래밍에서 함수(function)와 같다고 보면 되며,

이들은 프로그램을 이해하기 쉽고 재사용이 가능하도록 프로그램을 구조화하는 방법 중 하나이다.

 

인수는 프로시저에 값을 보내고 결과를 받아오는 일을 하므로,

프로그램의 다른 부분 및 데이터와 프로시저 사이의 인터페이스 역할을 한다.

 

따라서 프로시저는 소프트웨어의 추상화를 구현하는 방법이다.

 

 

프로그램이 프로시저를 실행하는 6단계

 

메인 루틴을 Caller(호출 프로그램), 프로시저를 Callee(피호출 프로그램)이라고 하자.

 

1. Caller는 Callee가 접근할 수 있는 곳에 인수를 넣는다.

$a0 ~ $a3 레지스터 - argument 저장

 

2. Caller는 Callee에게 제어를 넘긴다.

 

3. Callee가 필요로 하는 메모리 자원(stack 또는 register)을 요청하여 확보한다.

 

4. Callee가 필요한 작업을 수행한다.

 

5. Caller가 접근할 수 있는 장소에 Callee가 결과 값을 넣는다.

$v0 ~ $v1 레지스터 - return variable 저장

 

6. Callee는 프로그램 내의 여러 곳에서 호출될 수 있으므로, Caller(원래 위치)에게로 제어를 돌려준다.

$ra - return address 저장

 

* 프로시저 호출이 다른 부분에 영향을 미쳐서는 안 되기 때문에

호출 프로그램이 사용하는 모든 레지스터는 복귀하기 전에 프로시저 호출 전의 상태로 되돌려 놓아야 한다.


레지스터는 데이터를 저장하는 가장 빠른 장소이기 때문에 가능한 한 많이 사용하는 것이 좋다.

MIPS에서는 다음의 프로시저 호출 관례에 따라 레지스터 32개를 할당한다.

 

  • $a0 ~ $a3
    전달할 인수를 가지고 있는 인수 레지스터 4개

  • $v0 ~ $v1
    반환되는 값을 갖게 되는 값 레지스터 2개

  • $ra
    호출한 곳으로 되돌아가기 위한 복귀 주소를 가지고 있는 레지스터 1개

 

레지스터의 역할

 

 

프로시저를 위한 명령어

 

MIPS 어셈블리 언어는 레지스터를 할당할 뿐만 아니라 프로시저를 위한 명령어도 제공한다.

 

- jal(jump-and-link) 명령어

지정된 주소로 점프하면서 동시에 다음 명령어의 주소를 $ra 레지스터에 저장하는 명령이다.

즉, $ra 레지스터에 PC+4 값을 저장하는 것이다.

jal ProcedureAddress # jump and link

 

jal은 J-format을 따른다.

 

 

 

이름에서 link는 프로시저 종료 후 올바른 주소로 되돌아갈 수 있도록

호출한 곳과 프로시저 사이에 주소 또는 링크를 형성한다는 뜻이다.

 

- jr(jump register) 명령어

31번 레지스터 $ra에 기억되는 링크(link)를 복귀 주소(return address)라고 부른다.

한 프로시저가 여러 곳에서 호출될 수 있기 때문에 복귀 주소는 꼭 필요하다.

 

이것을 지원하기 위해서 MIPS는 jr 명령을 이용한다.

 

이 명령은 레지스터에 저장된 주소로 무조건 점프하라는 뜻이다.

jr $ra # return

즉, 저장된 return address(PC+4)로 복귀하게 되는 것이다.

 

jr 명령어는 R-format을 따른다.

 


레지스터 스필링(spilling)

컴파일러가 프로시저를 번역하는 데 레지스터의 개수가 부족한 경우 어떻게 될까?

 

컴퓨터가 갖고 있는 레지스터보다 프로그램에서 사용하는 변수가 더 많은 경우가 있다.

 

이때 컴파일러는 자주 사용되는 변수를 가능한 한 많이 레지스터에 넣고,

나머지 변수는 메모리에 저장했다가 필요할 때 꺼내서 레지스터에 넣는다.

 

자주 사용하지 않는 또는 한참 후에 사용할 변수를 메모리에 넣는 일을 레지스터 스필링(spilling)이라고 한다.

 

레지스터는 메모리보다 접근시간이 짧고 처리량도 많기 때문에

레지스터에 저장된 데이터를 사용하면 시간이 절약되고 사용하기도 편리하며, 에너지도 적게 든다.

 

따라서 좋은 성능과 에너지 절약을 위해서는 컴파일러가 레지스터를 효율적으로 사용해야 한다.

 

레지스터 스필링에 이상적인 자료구조는 스택(stack)이다.

스택은 후입 선출(Last-In-First-Out) 큐로 구성되었다.

 

스택에는 1. 다음 프로시저가 스필 할 레지스터를 저장할 장소나 2. 레지스터의 옛날 값이 저장된 장소를 표시하기 위해

가장 최근에 할당된 주소를 가리키는 포인터가 필요하며, 이 포인트를 스택 포인터(stack pointer)라고 부른다.

 

MIPS 소프트웨어는 스택 포인터를 위해 레지스터 29를 할당해 놓고 있으며, 이름은 $sp이다.

 

 

이 스택 포인터는 레지스터 값 하나가 스택에 저장되거나 스택에서 복구될 때마다 한 워드(word)씩 조정된다.

 

스택은 높은 주소에서 낮은 주소 쪽으로 성장하므로

스택에 푸시(push)할 때 스택 포인터 값은 감소, 스택에서 팝(pop)할 때 스택 포인터 값은 증가시켜야 한다.

* 참고 : 2022.07.08 - [Computer Science/Operating System] - [운영체제] Call Stack Frame & ESP, EBP 레지스터

 

1. 푸시(push) : 스택에 원소 추가

$sp = $sp - 4 # push

 

2. 팝(pop) : 스택에서 원소 제거

$sp = $sp + 4 # pop

 

 

 

스택을 통해서 프로시저들이 서로 같은 레지스터를 사용하지 않도록 해주어 레지스터 변형(register corruption)을 방지하게 된다.

 

즉, 레지스터 overwrite를 방지하기 위해

1. Callee 측에서 자신이 사용할 레지스터들에 저장된 데이터를 스택에 저장한 후 작업(task)을 수행하는 것이고,

2. Callee가 작업을 끝마치면 스택에 저장해놓은 데이터들을 다시 원래의 레지스터에 옮기고 난 다음에

    Caller에게 제어권을 넘기는 것이다.

 

 

다른 프로시저를 호출하지 않는 C 프로시저의 컴파일 (Leaf Procedure Example)

 

아래의 C 프로시저를 예시로 들어보자.

 

int leaf_example (int g, int h, int i, int j) 
{ 
    int f; 
    f = (g + h) - (i + j); 
    return f; 
}

 

다른 프로시저를 호출하지 않는 프로시저를 말단(leaf) 프로시저라고 한다.

 

이를 MIPS 어셈블리 언어로 번역하면 다음과 같다.

leaf_example:

    # adjust stack to make room for 3 items ($t1, $t0, $s0)
    addi $sp, $sp, -12		# 3 words = 12 bytes
    
    # save register for use afterwards
    sw   $t1, 8($sp)		# save $t1 on stack
    sw   $t0, 4($sp)		# save $t0 on stack
    sw   $s0, 0($sp)		# save $s0 on stack
    
    # Procedure body
    add  $t0, $a0, $a1
    add  $t1, $a2, $a3
    sub  $s0, $t0, $t1
    
    add  $v0, $s0, $zero	# Result
    
    # restore register for Caller
    lw   $s0, 0($sp)		# restore $s0
    lw   $t0, 4($sp)		# restore $t0
    lw   $t1, 8($sp)		# restore $t1
    
    # adjust stack to delete 3 items
    addi $sp, $sp, 12
    
    # jump back to calling routine
    jr   $ra			# Return

 

재귀 프로시저의 컴파일 (Non-Leaf Procedure Example)

 

프로시저는 다른 프로시저를 호출할 수 있으며, 자기 자신을 호출하는 재귀(recursive) 프로시저도 있다.

 

아래는 n 계승을 계산하는 재귀 프로시저이다.

 

int fact (int n) {
    if (n < 1) return 1;
    else return n * fact(n - 1);
}

 

이를 MIPS 어셈블리 언어로 번역하면 다음과 같다.

인수 n은 레지스터 $a0에 저장하며, 결과는 레지스터 $v0에 저장한다.

fact:
    addi $sp, $sp, -8 		# adjust stack for 2 items
    
    sw   $ra, 4($sp) 		# save the return address
    sw   $a0, 0($sp) 		# save the argument n
    
    slti $t0, $a0, 1 		# test for n < 1
    beq  $t0, $zero, L1 	# if n >= 1, go to L1
    
    addi $v0, $zero, 1 		# n < 1: result is 1
    addi $sp, $sp, 8 		# pop 2 items from stack
    jr   $ra 			# and return to Caller
    
L1: addi $a0, $a0, -1 		# n >= 1: argument gets (n - 1)
    jal  fact 			# recursive call with (n - 1)
    
    # 돌아갈 준비
    lw   $a0, 0($sp) 		# restore original argument n
    lw   $ra, 4($sp) 		# restore the return address
    addi $sp, $sp, 8 		# adjust stack pointer to pop 2 items
    
    mul  $v0, $a0, $v0 		# return n * fact(n - 1)
    
    jr   $ra 			# return to the Caller

프로시저 프레임 (Prodecure Frame)

레지스터에 들어가지 못할 만큼 큰 배열이나 구조체 같은 지역 변수를 저장하는 데도 스택이 사용되기 때문에 문제가 복잡해진다.

 

프로시저의 저장된 레지스터와 지역 변수를 가지고 있는 스택 영역을

프로시저 프레임(procedure frame) 또는 액티베이션 레코드(activation record)라고 부른다.

 

 

다음은 a. 프로시저 호출 전, b. 프로시저 호출 중, c. 프로시저 호출 후의 스택 할당 상태를 나타낸 그림이다.

 

* 프레임 포인터 $fp : 프로세저의 저장된 레지스터와 지역 변수의 위치를 표시하는 값

 

프레임 포인터($fp)는 프레임의 첫번째 워드를 가리키며, 스택 포인터($sp)는 스택의 맨 위를 가리킨다.

 

프로시저를 호출하면 저장해야 하는 모든 레지스터와 메모리 내의 지역 변수를 넣기 위한 공간을 스택에 만든다.

 

스택 포인터 값은 프로그램이 실행되면서 프로시저 내에서 바뀔 수 있기 때문에 변수 참조는 프레임 포인터를 사용하는 것이 좋다.

프레임 포인터는 변하지 않는 베이스 레지스터 역할을 하여 지역 변수 참조가 간단해진다.

 

프로시저를 호출할 때 $sp의 값으로 $fp를 초기화하고, 나중에 $fp로 $sp를 원상 복구한다.


MIPS의 메모리 할당 방식

 

스택에 저장되는 자동 변수 외에도 정적 변수와 동적 자료구조(malloc)를 위한 메모리 공간이 필요하다.

나머지 메모리 구조는 어떻게 사용될까?

 

Reserved

최하위 주소 부분은 사용이 유보되어 있다.

 

Test

MIPS 기계어 코드가 들어가는 부분이다.

전통적으로 텍스트 세그먼트(text segment)라 부른다.

 

Static data

정적 데이터 세그먼트(static data segment) 부분으로,

상수와 기타 정적 변수들이 이곳에 들어간다.

C에서 정적 배열은 그 크기가 고정되어 있어서 정적 데이터 세그먼트에 잘 맞는다.

 

힙(Heap)

malloc으로 할당한 배열이나 linked list처럼 늘어났다 줄어들었다하는 자료구조가 들어가는 부분이다.

힙은 스택과 마찬가지로 동적인 길이를 갖고 있고, 아래에서 위로 자란다.

 

스택(Stack)
자동 변수, 지역 변수가 저장되는 공간이다.

최상위 주소에서부터 시작해서 아래쪽으로 자란다.

 

스택과 힙은 서로 마주보면서 자라도록 할당하기 때문에 메모리를 효율적으로 사용할 수 있다.


C에서는 이러한 메모리 할당을 프로그램이 통제하는데, 이 부분이 흔하고도 까다로운 여러 버그의 근원이다.

 

malloc 후 free하는 것을 잊어 메모리 누출(memory leak)이 발생하여

메모리 부족으로 운영체제가 붕괴될 수 있고,

 

반면에 너무 일찍 반납하면

프로그램 의도와 상관없이 엉뚱한 곳을 가리키는 매달린 포인터(dangling pointer)가 발생한다.

 

Java에서는 이러한 버그를 피하기 위해 자동 메모리 할당과 가비지 컬렉션(garbage collection)을 사용한다.

저작자표시 (새창열림)

'컴퓨터 구조 > Ch2. 명령어 : 컴퓨터 언어' 카테고리의 다른 글

10. 병렬성과 명령어: 동기화  (0) 2023.04.13
9. MIPS의 주소 지정 방식  (0) 2023.04.13
7. 판단을 위한 명령어  (0) 2023.03.28
6. 논리 연산 명령어  (0) 2023.03.28
5. 명령어의 컴퓨터 내부 표현  (0) 2023.03.28
'컴퓨터 구조/Ch2. 명령어 : 컴퓨터 언어' 카테고리의 다른 글
  • 10. 병렬성과 명령어: 동기화
  • 9. MIPS의 주소 지정 방식
  • 7. 판단을 위한 명령어
  • 6. 논리 연산 명령어
smile blog
smile blog
건국대 첨단바이오공학부 & 컴퓨터공학부 BT & IT 기술로 희망을 꿈 꿉니당
  • smile blog
    스마일 블로그
    smile blog
  • 전체
    오늘
    어제
    • 분류 전체보기 (817)
      • 일상 생각들 (2)
      • 학과에 대해 (4)
        • 첨단바이오공학부 (4)
        • 컴퓨터공학부 (0)
      • -------- 프로젝트 -------- (0)
      • [DS] 토이 프로젝트 (1)
      • [Web, Game, XR] 토이 프로젝트 (11)
      • 경진대회 (1)
      • -------- 진로 -------- (0)
      • 생물정보학자 (18)
        • 데이터 과학이란? (0)
        • 되는 방법 (8)
        • 책 추천 (2)
        • 인강 (1)
        • 대학 (2)
        • 회사 (1)
        • 학원 (2)
        • 학회 (2)
      • 디지털 헬스케어 (72)
        • 방법 (8)
        • 생각들 (10)
        • 공부법 (4)
        • 책 추천 (2)
        • 학원 (2)
        • 참고 (2)
        • 대학 (3)
        • 회사 (3)
        • 인강 (2)
        • 게임 엔진들 (1)
        • 게임 프로그래머 개론 (2)
        • 게임 프로그래머 취업 전략 가이드 (7)
        • 취업 서류 (1)
        • 애정하는 게임들 (4)
        • XR 테크니컬 아티스트 (9)
        • 영화, 애니메이션 테크니컬 디렉터 (12)
      • -------- 기초 학문 -------- (0)
      • 생명과학 이야기 (2)
        • 대학 강의 (2)
      • 화학 이야기 (0)
      • 컴퓨터과학 이야기 (0)
      • 통계학 이야기 (0)
      • 수학 이야기 (1)
        • 공학 수학 (1)
      • 영어 이야기 (1)
      • 심리학 이야기 (7)
        • 현대인과 정신건강 (7)
      • -------- 컴퓨터 언어 -------- (0)
      • Python (3)
        • 나도코딩의 파이썬 입문 (1)
        • 파이썬 관련 정보 (1)
      • SQL (0)
      • C 언어 (32)
        • 혼자 공부하는 C언어 요약 (1)
        • [책 정리] 혼자 공부하는 C언어 (31)
      • C++ (33)
        • 명품 C++ 프로그래밍 요약 (1)
        • [책 정리] 명품 C++ 프로그래밍 (27)
        • C++ STL (0)
        • 뇌를 자극하는 C++ STL (5)
      • -------- 생명과학 -------- (0)
      • 생화학 (5)
        • 대학 강의 (5)
      • 분자세포생물학 (3)
        • 대학 강의 (3)
      • 유전자치료공학 (2)
        • 대학 강의 (2)
      • 생명정보학 (5)
        • 대학 강의 (5)
      • 약리학 (2)
        • 대학 강의 (2)
      • -------- 컴퓨터과학 -------- (0)
      • 자료구조와 알고리즘 (8)
        • 자료구조와 알고리즘의 정의 (3)
        • [책 정리] C언어로 쉽게 풀어쓴 자료구조 요약 (1)
        • [인강] 자료구조와 알고리즘 (2)
        • 코딩 테스트 대비하기! (1)
      • 컴퓨터 회로 (0)
      • 컴퓨터 구조 (43)
        • 컴퓨터 구조와 운영체제 요약 (1)
        • ---------------------------------------- (0)
        • [전공 책 정리] 컴퓨터 구조 및 설계 (1)
        • Ch1. 컴퓨터 추상화 및 관련 기술 (8)
        • Ch2. 명령어 : 컴퓨터 언어 (11)
        • Ch3. 컴퓨터 연산 (8)
        • Ch4. 프로세서 (11)
        • Ch5. 메모리 계층구조 (3)
        • Ch6. 병렬 프로세서 : 클라이언트에서 클라우드까지 (0)
      • 시스템 프로그래밍 (15)
        • [책 정리] 시스템 프로그래밍 유닉스 & 리눅스 (0)
        • [인강] 리눅스 시스템 프로그래밍 (2)
        • 리눅스에서 코딩이란? (8)
        • 대학교 강의 정리 (5)
      • 운영체제 (0)
      • 컴퓨터 네트워크 (37)
        • 모두의 네트워크 요약 (1)
        • [책 정리] 모두의 네트워크 (10)
        • ---------------------------------------- (0)
        • [전공 책 정리] 컴퓨터 네트워킹 하향식 접근 8판 (1)
        • Ch1. 컴퓨터 네트워크와 인터넷 (7)
        • Ch2. 애플리케이션 계층 (7)
        • Ch3. 트랜스포트 계층 (8)
        • Ch4. 네트워크 계층 : 데이터 평면 (3)
        • Ch5. 네트워크 계층 : 제어 평면 (0)
        • Ch6. 링크 계층과 근거리 네트워크 (0)
        • Ch7. 무선 및 이동 네트워크 (0)
        • Ch8. 컴퓨터 네트워크 보안 (0)
      • 데이터베이스 (1)
      • -------- 데이터과학 -------- (0)
      • 데이터 사이언스 (8)
        • 인강 (8)
      • 데이터 분석 (2)
        • 인강 (2)
      • 머신러닝 (2)
        • 대학 수업 (2)
      • 인공지능 (11)
        • 대학교 강의 정리 (10)
        • 인공지능 관련 정보 (1)
      • -------- +a -------- (0)
      • Visual Studio Community (7)
        • 설치법 (1)
        • 단축키 (1)
        • 오류 (5)
      • Visual Studio Code (0)
      • 노션 (1)
      • 깃허브 (7)
        • 깃허브 사용법 (5)
        • 유니티, 언리얼 & 깃허브 (1)
        • 깃허브 주의사항 (1)
      • 챗GPT 활용법 (0)
      • 기타 feat. 프로그래밍 (7)
        • 프로그래머로 살아남기 (5)
        • 코딩 vs 프로그래밍 (1)
        • 애플 비전 프로 (1)
      • 메타버스 (5)
      • -------- 예술 -------- (0)
      • 음악 (1)
      • 미술 (0)
      • -------- XR -------- (0)
      • 유니티 이야기 (23)
        • 레트로의 유니티 게임 프로그래밍 에센스 요약 (4)
        • 유니티 관련 정보 (1)
        • 유니티 디버깅 (13)
        • 유니티 인강 (3)
        • 대학교 게임 프로그래밍 강의 (2)
      • 언리얼 이야기 (0)
        • 인생 언리얼 교과서 요약 (0)
      • 컴퓨터 그래픽스 (6)
        • OpenGL (6)
      • 가상현실 & 증강현실 (4)
        • 유니티 vr (4)
      • HCI 와 UI UX (7)
        • [책 정리] HCI 개론 (6)
      • -------- Design -------- (0)
      • 캐릭터 (1)
        • 모델링 (0)
        • 리깅 (1)
      • 포토샵 (3)
      • 3ds Max (7)
      • Maya (9)
        • 블로그 (1)
        • 인강 (6)
        • 대학교 (2)
      • Blender (14)
        • 책 (1)
        • 인강 (7)
        • 기타 (3)
        • 대학교 (3)
      • 아트 작업물들 (2)
      • 에셋 사이트 (1)
      • -------- 건강관리 -------- (0)
      • 건강관리 ft. 정현 (12)
        • 목 디스크 (2)
        • 눈 관리 (2)
        • 일상생활 습관 (6)
        • 일상생활 꿀팁 (2)
        • 사무직 꿀팁 (0)
      • 헬스의 정석 ft. 정현 (28)
        • 헬스와 건강 (8)
        • 헬스 구체화 정보 (6)
        • 헬스 유튜버 (1)
        • 헬스 서적 (1)
        • 도전 바디프로필! (11)
        • 헬스장 패션 (1)
      • -------- etc -------- (0)
      • 진로 관련 잡다한 글들 (34)
        • 진도율 (9)
        • 진로 관련 글들 (15)
        • 학교 강의 관련 글들 (10)
      • 인생 꿀 Tip (23)
        • 컴퓨터 초기 설정 (9)
        • 원격 데스크톱 (1)
        • 노트북 발열 (1)
        • 전자기기 (2)
        • 중고기기 팔기 (1)
        • 아이패드 필기 어플 (1)
        • 에어팟 (1)
        • 커피 (1)
        • 맥북 (1)
        • lg 그램 (1)
        • 검색엔진에서 내 티스토리 검색 (1)
        • hELLO 다크 모드 없애기 (1)
        • 인터넷 연결 문제 (1)
        • 키보드 문제 해결 (1)
      • 유튜브 (3)
      • 청춘 그리고 추억 (1)
      • 인생 계획표 (2)
        • 2024년 2학기 (1)
        • 2024년 여름방학 (0)
        • 2024년 1학기 (0)
        • 2023년 겨울방학 (1)
      • 다양한 글들 (98)
        • C++ STL (6)
        • Win32 API (24)
        • PushPush 게임 (13)
        • 컴퓨터구조 (1)
        • 자료구조와 알고리즘 (50)
        • 게임의 정의 (3)
        • 영상 회사 (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

    • Dream
    • 코딩을 시작한 이유
    • 나를 소개합니다!
    • 블로그 공부법
    • IT & 가치 있는 일들
  • 인기 글

  • 태그

    건국대
    의생명공학
    C언어
    데이터사이언스
    연산자
    의생명공학과
    생물정보학
    코드잇
    unity
    첨단바이오공학부
    AI
    스택
    생명공학
    배열
    블렌더
    심리학
    C++
    리눅스 터미널
    유니티
    인공지능
    데이터과학
    컴퓨터구조
    알고리즘
    포인터
    함수
    C++ STL
    컴퓨터 네트워크
    자료구조
    리눅스
    명령어
  • 최근 댓글

  • hELLO· Designed By정상우.v4.10.3
smile blog
8. 하드웨어의 프로시저 지원
상단으로

티스토리툴바