2. 서브루틴 목적 코드반복 막음 재사용 코드조각을 단 한 장소에 두고 서브루틴이 완료된 후에 주 프로그램이 적절하게 다시 시작되도록 만듦 이를 위해 약간의 추가적인 명령들을 집어넣음
3. MIX에서의 서브루틴 구현 J 레지스터 사용 장점 프로그램 공간 절약 프로그램 적재시간 줄임 작은 메모리로 인한 고속 메모리 사용 가능 크고 복잡한 프로그램의 구조화 전체 문제의 논리적인 분할 구조 형성 디버깅 쉬워짐 작성한 사람 이외의 사람도 사용할 수 있음 단점 서브루틴에 들어오고 나가는데 걸리는 추가 시간 => 일반적으로 무시할 수 있는 수준임
4. 가장 간단한 서브루틴 하나의 진입점(entry)과 하나의 출구(exit) 실행 : JMP MAX100 결과 X+1~X+100에서 가장 큰 값이 레지스터A에 저장 rI2에 그 값의 위치 저장 * MAXIMUM OF X[1..100] MAX100 STJ EXIT *서브루틴 연계 ENT3 100 *M1. 초기화 JMP 2F 1H CMPA X,3 *M3. 비교 JGE *+3 2H ENT2 0,3 *M4. m을 변경 LDA X,3 *새 최대값을 찾았음 DEC3 1 *M5. k를 감소 J3P 1B *M2. 모두 판정했는가? EXIT JMP * *주 프로그램으로 돌아간다.
5. 실행 코드 수정? MIX에서는 반환 주소를 코드 영역에 저장한다. MMIX같은 새로운 컴퓨터는 레지스터나 특별한 배열에 저장해 둔다.
6. 절약하는 코드의 양 코드 조각 사이즈 : k m군데에서 반복됨 STJ, JMP 필요 전체적으로 m+k+2개의 메모리 요구 서브루틴 사용하지 않을때는 mk 절약양 : (m-1)(k-1)-3 m=1 or k=1 이면 공간 절약되지 않음 k=2이면 4보더 커야 이득
7. 손실되는 시간의 양 추가적인JMP, STJ, 서브루틴 호출을 위한 JMP 서브루틴이 t번 쓰인다면 4t?의 시간주기들이 필요함. 대신 서브루틴은 일반적인 경우에 맞게 코딩해야 하므로 추가적인 명령이 필요할 수 있음.
8. 매개변수(parameter) 호출명령열(calling sequence) : 제어를 서브루틴으로 옮기고 서브루틴이 적절히 시작하게 만드는 서브루틴 외부의 코드 인수(argument) : 서브루틴을 호출할 때 제공된 매개변수의 구체적인 값 ENT1 n JMP MAXIMUM 공간절약량 : (m-1)(k-c)-상수
9. 레지스터 내용 파괴 못하게 rI3 백업해둠 ST3 3F(0:2) 3H ENT3 * 시간 : 추가적인 코드 2줄 + 서브루틴호출 3주기
10. 서브루틴 명세 호출 명령열 : JMP MAXIMUM 들어올 때 조건 : rI1 = n; n>=1이라고 가정 나갈 때 조건 : rA = max CONTENTS(X+k) = CONTENTS(X+rI2); rI3 = 0; rJ와 CI도 영향을 받음
11. 다중진입점 MAX100 ENT3 100 *첫째 진입점 MAXN STJ EXIT *둘째 진입점 JMP 2F *(1)에서와 마찬가지로 진행 … EXIT JMP * *주 프로그램으로 돌아간다. 셋째 진입점 추가 MAX50 ENT3 50 JSJ MAXN *JSJ : Jump w/o rJ
12. 매개변수 전달 레지스터를 통한 전달 고정된 메모리 칸들에 저장 JMP다음에 그냥 매개변수들을 나열 JMP MAXN CON n 수정된 서브루틴 MAXN STJ *+1 ENT1 * *rI1 = rJ LD3 0,1 *rI3 = n JMP 2F *(1)과 마찬가지로 진행 … J3P 1B JMP 1,1 *복귀
14. 다중 출구(Multiple Exits) MAX100 ENT3 100 *n=100일 때의 진입점 MAXN STJ EXIT *일반적인 n일때의 진입점 JMP 2F (1)과 마찬가지로 진행 … J3P 1B JANP EXIT *최대값 <=0이면 정상적인 출구를 취한다. STX TEMP CMPA TEMP JGE EXIT *최대값 >= rX이면 정상적인 출구룰 취한다. ENT3 1 *아니면 둘째 출구를 취한다. EXIT JMP *,3 *적절한 장소로 돌아간다. *+rI3
15. 서브루틴의 서브루틴 호출 중첩 호출 자기자신을 호출하는 다른 서브루틴을 호출하면 안됨 (주소 안의 지점이 깨짐)
16. 복잡하고 긴 프로그램의 접근 방식 단계0. (초기아이디어) 프로그램이 사용할 일반적인 공략 계획을 어렴풋하게나마 결정 단계1. (프로그램의 대략적인 스케치) 전체 프로그램을 좀 더 작은 조각으로 계속 분할해 나감. 표현은 자유롭게 함. 서브루틴을 정의함. 단계2. (최초의 실제 작동 가능 프로그램) 저수준 서브루틴부터 주프로그램 순으로 실제 코드 작성. 서브루틴 작성시 서브루틴이 어떤 일을 하며 그 호출 명령열은 무엇인지를 정리함. - TEMP가 겹치지 않도록 주의. TEMPj를 사용하고 Depth에 따라 j를 증가시킴. 단계3. (재조사) 서브루틴 범위 조정 - 서브루틴 전 후의 일들을 포함하여 좀더 일반화 - 여러 서브루틴을 합침 - 만들 필요 없는 서브루틴 발견 - 호출되지 않는 서브루틴 제거 * 단계1로 돌아가길 주저하지 말 것. 이전보다 훨씬 쉬우며 이것이 오히려 나중에 디버깅하는 시간을 크게 줄여줄 수 있음. 반복하다 보면 이렇게 했을 때 이득이 줄어드는 순간에 다다르게 됨. 단계4. (디버깅) 프로그램 수행 순서로 프로그램을 연구.실제로 기대했던 대로 일어나는지를 점검함. 적절한 검사 자료 준비. 프로그램의 상당 부분을 디버깅 공정으로 사용함으로써 생산성이 놀랄만큼 향상됨. 실수를 기록해 둠. 위의 내용은 1964년 기준임 80년대에 구조적 문서화(Structured Documentation) 문학적 프로그래밍(Literate Programming) 기법 활용됨