LAB‎ > ‎

Lab 17

1) [프로그램 1]을 실행하고 인터럽트 핸들러 코드의 구조를 파악하시오
- Jump Table을 통한 실행 흐름 파악

2) [프로그램 2]를 실행하고 관찰하시오.
- DMA가 처리가 완료되어 인터럽트(IRQ1)가 걸릴 때 처리 방법
- 이전 IO 요청이 처리가 되었는지 확인하는 방법(INT 5)
- 이런 방법에 아직 잠재적으로 남아 있는 문제에 대한 설명

3) [프로그램 2]를 DMA 완료를 기다리는 대기 사이사이에 계산을 분산하여 더 빨리 실행하도록 수정하시오.
- 원래 프로그램은 싸이클이 3103 정도 걸릴 것이다.
- 힌트: 싸이클을 2560 정도까지 줄일 수 있음

4) [프로그램 3]을 실행하며 관찰하시오.
- PC 값의 변화: 1000, 2000, 3000 번지 대 
- 7 Segment register 값의 변화:  DATA, DMASRC, DMADST
- 종료 싸이클 수

5) [프로그램 3]의 TCB0과 TCB1을 다음과 같이 바꾸면서 실행해 보시오.
(1) 두 개 모두 CPU_BOUND_TASK로 설정
(2) (1)의 상황인데 Multi Tasking이 일어나도록 변경 - "INT 1"(Yield)을 적절히 삽입
(3) 위와 같이 실행하면서 다음 사항을 관찰하고 설명하시오.
- INT 1(Yield)의 역할
- INT 2(Finish)의 역할
- TCB0, TCB1의 상태가 모두 Finished(-1)이면 어떤 절차에 의해서 어떤 일이 일어나는가?

6) [프로그램 3]의 TCB0과 TCB1의 PC 초기값을 서로 바꾸어 실행해보시오.
- TCB0: IO_BOUND_TASK, TCB1: CPU_BOUND_TASK(INT 1(Yield) 없음)
- 병행 실행이 일어났는가?
- 종료 싸이클 수 
- 4), 5)를 실행해서 싸이클 수로 다음 표를 채우시오.
  n=15 n=20
4) 병행실행 (A) 
5) 순차실행 (B) 
 비율 (B-A)/B % 

7) [프로그램 3]의 TCB0과 TCB1를 모두 IO_BOUND_TASK로 바꾸어서 실행해 보시오.
(1) 무슨일이 예상되는가?
(2) IO_BOUND_TASK2를 다음과 같이 새로 만들어서 IO_BOUND_TASK와 병행 실행하며 관찰하시오.
    - IO_BOUND_TASK와 같은데 메세지만 "9876543210"으로 바꿈
(3) (2)에서 DMA가 완료되어 인터럽트를 걸고 이를 처리하면서 DMAFLAG가 세팅되는데 이를 기다리는 Task는 두 개이다. 누가 이 결과를 받아 진행할지 알 수 있는가?
(4) 출력장치(7 Segment)를 두 개 만들어 서로 구별되게 만들어 보시오.


++++++++++++++++++++++++++++
[프로그램 1]

// V09 two buttons, JMP Table
//$DEV SIMPLE-BUTTON 5
//$DEV SIMPLE-BUTTON 7
IO_BRIDGEEQU0
PIC_IRREQU96
PIC_ISREQU97
PIC_CMDEQU98
PIC_IMREQU99
SIMPLE_INTSTART0
LDA P_IH_ENTRY// initialize IH register
LDIH A
LOOP
COB
JMPLOOP
ORG10
IH_ENTRYSGMT// PC, ST, PSR are saved in iRTN, iST, iPSR
// Interrupt Mask is ON in PSR
// set PSR to current segment
SWAPA SP// A를 SP에 저장
// A는 인터럽트 걸린 프로그램에서 사용 중일 수 있으므로 보존해야 함
// SP는 iSP에 저장되어 있고으므로 손상되어도 됨
LDA S_STACK_BTM// 시스템스택포인터를 A에 읽어옴
SWAPA SP// A를 복원하면서 동시에 SP를 세팅
// PUSHALL 하기 전에 visible register(SP 제외)를 손상하면 안됨
PUSHALL// save context info(visible registers) of interrupted program
MOVA SP
STA CONTEXT
// find out reason
CLRC
MOVX EX
CMPX C
SKZ
JMPHANDLE_EXCEPTION
INPIC_ISR// Device interrupt
MOVX A
JMP*@IRQ_JUMP_TABLE
IH_EOIRTN
LDA PIC_EOI// EOI: important!!
OUTPIC_CMD
IH_RTNLDA CONTEXT
MOVSP A
POPALL// restore context info
IRET// restore PC, ST, PSR from iRTN, iST, iPSR
S_STACK_BTMBOX1000// Segment 0
CONTEXTRESBOX1// Starting addr of visible registers of the current task
HANDLE_EXCEPTION
CLREX// reset EX register: important!!
JMP*@EXCEPTION_JUMP_TABLE
HANDLE_IRQ1
LDA BUTTON_COUNT
INCA
STA BUTTON_COUNT
OUTIO_BRIDGE
JMPIH_EOIRTN
HANDLE_IRQ2
LDA BUTTON_COUNT
DECA
STA BUTTON_COUNT
OUTIO_BRIDGE
JMPIH_EOIRTN
IRQ_JUMP_TABLE
BOXIH_EOIRTN// IRQ 0
BOXHANDLE_IRQ1// IRQ 1
BOXHANDLE_IRQ2// IRQ 2
BOXIH_EOIRTN// IRQ 3
BOXIH_EOIRTN// IRQ 4
BOXIH_EOIRTN// IRQ 5
BOXIH_EOIRTN// IRQ 6
BOXIH_EOIRTN// IRQ 7
BOXIH_EOIRTN// IRQ 8
BOXIH_EOIRTN// IRQ 9
EXCEPTION_JUMP_TABLE
BOXIH_RTN// EX 0
BOXIH_RTN// EX 1
BOXIH_RTN// EX 2
BOXIH_RTN// EX 3
BOXIH_RTN// EX 4
BOXIH_RTN// EX 5
BOXIH_RTN// EX 6
BOXIH_RTN// EX 7
BOXIH_RTN// EX 8
BOXIH_RTN// EX 9
// Exception number 범위 끝까지 …
P_IH_ENTRYBOXIH_ENTRY
PIC_MASKONBOX100
PIC_MASKOFFBOX200
PIC_MASKSETBOX300
PIC_ICLBOX997
PIC_ICEBOX998
PIC_EOIBOX999
BUTTON_COUNTBOX0

++++++++++++++++++++++++++++
[프로그램 2]

// V09 SEG IO, DMA
//$DEV SEVEN-SEGMENT-D 10 10 1
IO_BRIDGEEQU0
PIC_IRREQU96
PIC_ISREQU97
PIC_CMDEQU98
PIC_IMREQU99
MMIO_BASEEQU100
MMIO_SEG_DATAEQUMMIO_BASE+10// IO Address for 7 segments
MMIO_SEG_STATEEQUMMIO_BASE+11
MMIO_SEG_CMDEQUMMIO_BASE+12
MMIO_SEG_DMASRCEQUMMIO_BASE+13
MMIO_SEG_DMADSTEQUMMIO_BASE+14
ORG0
INIT// set PSR to current segment
LDA P_IH_ENTRY
MOVIH A
JMPIO_BOUND_TASK
COB// will not come back here
// Command for 7 segments
SEG_WRITEBOX100
SEG_ONBOX200
SEG_OFFBOX300
SEG_ON_ALLBOX992
SEG_OFF_ALLBOX993
SEG_DMA_WRITEBOX991
SEG_DMA_READBOX994
SEG_DMA_RESETBOX999
MASK_READYBOX9// Mask bits
SEG_DMA_READYBOX301
ORG200
IH_ENTRYSGMT// PC, ST, PSR are saved in iRTN, iST, iPSR
// Interrupt Mask is ON in PSR
// set PSR to current segment
SWAPA SP// A를 SP에 저장
// A는 인터럽트 걸린 프로그램에서 사용 중일 수 있으므로 보존해야 함
// SP는 iSP에 저장되어 있고으므로 손상되어도 됨
LDA S_STACK_BTM// 시스템스택포인터를 A에 읽어옴
SWAPA SP// A를 복원하면서 동시에 SP를 세팅
// PUSHALL 하기 전에 visible register(SP 제외)를 손상하면 안됨
PUSHALL// save context info(visible registers) of interrupted program
MOVA SP
STA CONTEXT
// find out reason
CLRC
MOVX EX
CMPX C
SKZ
JMPHANDLE_EXCEPTION
INPIC_ISR// Device interrupt
MOVX A
JMP*@IRQ_JUMP_TABLE
IH_EOIRTN
LDA PIC_EOI// EOI: important!!
OUTPIC_CMD
IH_RTNLDA CONTEXT
MOVSP A
POPALL// restore context info
IRET// restore PC, ST, PSR from iRTN, iST, iPSR
S_STACK_BTMBOX1000// Segment 0
CONTEXTRESBOX1// Starting addr of visible registers of the current task
HANDLE_EXCEPTION
CLREX// reset EX register: important!!
JMP
*@EXCEPTION_JUMP_TABLE
HANDLE_IRQ1
LDA SEG_DMA_READY
MOVD0 A
LDA MMIO_SEG_STATE
CMPA D0
SKZ
JMPIH_EOIRTN
LDA #1// set flag
STA DMAFLAG
JMPIH_EOIRTN
DMAFLAGBOX0
HANDLE_TRAP5
LDA DMAFLAG
CLRC
CMPA C
SKNE
JMPIH_RTN
CLRA
STA DMAFLAG// reset dma flag
LDA P_CURR_CTX
MOVB A
CLRX
STCTX@%0
MOVA R
STA CURR_CTX_PC
LDCTX@%0
JMPIH_RTN
P_CURR_CTXBOXCURR_CTX_PC
CURR_CTX_PCRESBOX1
CURR_CTX_PSRRESBOX1
CURR_CTX_SPRESBOX1
IRQ_JUMP_TABLE
BOXIH_EOIRTN// IRQ 0
BOXHANDLE_IRQ1// IRQ 1
BOXIH_EOIRTN// IRQ 2
BOXIH_EOIRTN// IRQ 3
BOXIH_EOIRTN// IRQ 4
BOXIH_EOIRTN// IRQ 5
BOXIH_EOIRTN// IRQ 6
BOXIH_EOIRTN// IRQ 7
BOXIH_EOIRTN// IRQ 8
BOXIH_EOIRTN// IRQ 9
EXCEPTION_JUMP_TABLE
BOXIH_RTN// EX 0
BOXIH_RTN// EX 1
BOXIH_RTN// EX 2
BOXIH_RTN// EX 3
BOXIH_RTN// EX 4
BOXHANDLE_TRAP5// EX 5
BOXIH_RTN// EX 6
BOXIH_RTN// EX 7
BOXIH_RTN// EX 8
BOXIH_RTN// EX 9
// Exception number 범위 끝까지 …
P_IH_ENTRYBOXIH_ENTRY
// Commands for PIC(Programmable Interrupt Handler)
PIC_MASKONBOX100
PIC_MASKOFFBOX200
PIC_MASKSETBOX300
PIC_ICLBOX997
PIC_ICEBOX998
PIC_EOIBOX999
BUTTON_COUNTBOX0
IO_BOUND_TASK
LDA SEG_ON_ALL// Turn on all 7 segment displays
STA MMIO_SEG_CMD
CLRX
LOOP1
LDA @MSG_TABLE// request DMA IO
ST
A MMIO_SEG_DMASRC
CLRA// 7segment 장치의 buffer 주소는 0에서 시작
ST
A MMIO_SEG_DMADST
LDA MSG_LENG
STA MMIO_SEG_DATA
LDA SEG_DMA_WRITE
STA MMIO_SEG_CMD
WAIT_LOOP1SETRTNNEAR NEXT_IO
INT5// check dma flag
COB

JMPWAIT_LOOP1
NEXT_IO
INCX
LDA COUNT
CMPA X
SKZ
JMPLOOP1
LDA =80// Calculate something
MOVC A
CAL_LOOPLDA TOTAL
INCA
STA TOTAL
DECC
SKZ
JMPCAL_LOOP
COB
TOTALBOX0
COUNTBOX4
MSG_LENGBOX10
MSG_TABLEBOXMSG0
BOXMSG1
BOXMSG2
BOXMSG3
BOXMSG4
BOXMSG5
BOXMSG6
BOXMSG7
BOXMSG8
BOXMSG9
MSG0BOX0b00111111//0
MSG1BOX0b00000110//1
MSG2BOX0b01011011//2
MSG3BOX0b01001111//3
MSG4BOX0b01100110//4
MSG5BOX0b01101101//5
MSG6BOX0b01111101//6
MSG7BOX0b00000111//7
MSG8BOX0b01111111//8
MSG9BOX0b01101111//9
BOX0b01000000//-
BOX0b01000000//-
BOX0b01000000//-
BOX0b01000000//-
BOX0b01000000//-
BOX0b01000000//-
BOX0b01000000//-
BOX0b01000000//-
BOX0b01000000//-
BOX0b01000000//-
BOX0b01000000//-

++++++++++++++++++++++++++++
[프로그램 3]

// V09,Two Tasks, 순차실행, 예상싸이클 6193(n=15), 6777(n=20)
//$DEV SEVEN-SEGMENT-D 10 10 1 500
// Segment0 - Initialize after booting, System Stack
// Segment1 - Interrupt Handler, System library
// Segment2 - User Space(Program)
// Segment3 - User Space(Stack)
// Segment3 - User Space(Stack)
BEGIN_INITEQU0
BEGIN_SYSEQU1000
BEGIN_USER1EQU2000
BEGIN_USER2EQU3000
SEG_INITEQUBEGIN_INIT/1000
SEG_SYSEQUBEGIN_SYS/1000
SEG_USER1EQUBEGIN_USER1/1000
SEG_USER2EQUBEGIN_USER2/1000
IO_BRIDGEEQU0
PIC_IRREQU96
PIC_ISREQU97
PIC_CMDEQU98
PIC_IMREQU99
MMIO_BASEEQU100
MMIO_SEG_DATAEQUMMIO_BASE+10// IO Address for 7 segments
MMIO_SEG_STATEEQUMMIO_BASE+11
MMIO_SEG_CMDEQUMMIO_BASE+12
MMIO_SEG_DMASRCEQUMMIO_BASE+13
MMIO_SEG_DMADSTEQUMMIO_BASE+14
////////// Init segment & System Stack //////////
ORGBEGIN_INIT
INIT// set PSR to current segment
LDA P_IH_ENTRY
MOVIH A
SGMTTCB0_D3/1000
LDA TCB0_D3
MOVD3 A
LDA TCB0_SP
MOVSP A
LDA TCB0_PC
SGMT
MOVR A
JMP*R
COB// will not come back here
P_IH_ENTRYBOXIH_ENTRY
// Command for 7 segments
SEG_WRITEBOX100
SEG_ONBOX200
SEG_OFFBOX300
SEG_ON_ALLBOX992
SEG_OFF_ALLBOX993
SEG_DMA_WRITEBOX991
SEG_DMA_READBOX994
SEG_DMA_RESETBOX999
MASK_READYBOX9// Mask bits
SEG_DMA_READYBOX301
////////// System segmnt - Interrupt Handler, System library //////////
ORGBEGIN_SYS
IH_ENTRYSGMT// PC, ST, PSR are saved in iRTN, iST, iPSR
// Interrupt Mask is ON in PSR
// set PSR to current segment
SWAPA SP// A를 SP에 저장
// A는 인터럽트 걸린 프로그램에서 사용 중일 수 있으므로 보존해야 함
// SP는 iSP에 저장되어 있고으므로 손상되어도 됨
LDA S_STACK_BTM// 시스템스택포인터를 A에 읽어옴
SWAPA SP// A를 복원하면서 동시에 SP를 세팅
// PUSHALL 하기 전에 visible register(SP 제외)를 손상하면 안됨
PUSHALL// save context info(visible registers) of interrupted program
MOVA SP
STA CONTEXT
// find out reason
CLRC
MOVX EX
CMPX C
SKZ// if EX is zero
JMPHANDLE_EXCEPTION
INPIC_ISR// Device interrupt
MOVX A
JMP*@IRQ_JUMP_TABLE
IH_EOIRTN
LDA PIC_EOI
OUTPIC_CMD
IH_RTNLDA CONTEXT
MOVSP A
POPALL// restore context info
IRET// restore PC, ST, PSR from iRTN, iST, iPSR
S_STACK_BTMBOX1000// Segment 0
CONTEXTRESBOX1// Starting addr of visible registers of the current task
// Commands for PIC(Programable Interrupt Handler)
PIC_MASKONBOX100
PIC_MASKOFFBOX200
PIC_MASKSETBOX300
PIC_ICLBOX997
PIC_ICEBOX998
PIC_EOIBOX999
HANDLE_EXCEPTION
CLREX
JMP
*@EXCEPTION_JUMP_TABLE
HANDLE_IRQ1// IRQ 1: DMA인터럽트를 처리하여 DMAFLAG를 세팅
SGMTSEG_DMA_READY/1000
LDA SEG_DMA_READY
MOVD0 A
SGMTMMIO_SEG_STATE/1000
LDA MMIO_SEG_STATE
SGMT
CMPA D0
SKZ
JMPIH_EOIRTN
LDA #1// set flag
STA DMAFLAG
LDA PIC_EOI
OUTPIC_CMD
JMPTRAP1_YIELD
DMAFLAGBOX0
HANDLE_TRAP5// EX 5: DMAFLAG를 확인하여 R 레지스터 값으로 점프
LDA DMAFLAG
CLRC
CMPA C
SKNE
JMPIH_RTN
CLRA
STA DMAFLAG// reset dma flag
LDA P_CURR_CTX
MOVB A
CLRX
STCTX@%0
MOVA R
STA CURR_CTX_PC
LDCTX@%0
JMPIH_RTN
P_CURR_CTXBOXCURR_CTX_PC
CURR_CTX_PCRESBOX1
CURR_CTX_PSRRESBOX1
CURR_CTX_SPRESBOX1
TRAP1_YIELD
MOVX D3// D3: current task
LDA @TASK_PAIR
MOVD2 A// D2: new task
LDA P_TCB_START
MOVD1 A
LDA TCB_LENGTH
IMULA D2// D2: index for new task
ADDD1 A// D1: Addr for State of the task
MOVA *D1
CLRC
CMPA C
SKZ// if Ready
JMPIH_RTN// nothing to yield
JMPSWITCH_TASK
TRAP2_FINISH
LDA P_TCB_START
MOVD1 A
LDA TCB_LENGTH
IMULA D3// D3: index for the current task
ADDD1 A// D1: Addr for State of the current task
CLRA
DECA// A= -1
MOV*D1 A// set state to -1
JMPTRAP1_YIELD
IRQ_JUMP_TABLE
BOXIH_EOIRTN// IRQ 0
BOXHANDLE_IRQ1// IRQ 1: DMA인터럽트를 처리하여 DMAFLAG를 세팅
BOXIH_EOIRTN// IRQ 2
BOXIH_EOIRTN// IRQ 3
BOXIH_EOIRTN// IRQ 4
BOXIH_EOIRTN// IRQ 5
BOXIH_EOIRTN// IRQ 6
BOXIH_EOIRTN// IRQ 7
BOXIH_EOIRTN// IRQ 8
BOXIH_EOIRTN// IRQ 9
EXCEPTION_JUMP_TABLE
BOXIH_RTN// EX 0
BOXTRAP1_YIELD// EX 1: SWITCH_TASK between TID 0 & TID 1
BOXTRAP2_FINISH// EX 2: Finish Task
BOXIH_RTN// EX 3
BOXIH_RTN// EX 4
BOXHANDLE_TRAP5// EX 5: DMAFLAG를 확인하여 R 레지스터 값으로 점프
BOXIH_RTN// EX 6
BOXIH_RTN// EX 7
BOXIH_RTN// EX 8
BOXIH_RTN// EX 9
// Exception number 범위 끝까지 …
IDLE_TASKSGMT
COB
JMPIDLE_TASK
TASK_PAIR
BOX1
BOX0
SWITCH_TASK
// Stack에 중단된 task의 visible register가 있음
// D2: a new Task, D3: the current Task
MOVA #9// will move 9 visible registers
MOVC A
LDA CONTEXT
MOVD0 A// D0: Source: on Stack
SAVE_CURR_TASK
LDA P_TCB_VISIBLE
MOVD1 A
LDA TCB_LENGTH
IMULA D3// D3: index for the current task
ADDD1 A// D1: Block for Visible Reg of Current Task
MOVB D1
CLRX
STCTX@%-3// Save iRTN, iPSR, iSP to TCB
BLKMOV@*D1 @*D0// Block copy from D0 to D1 (C: counter)
RESTORE_NEW_TASK
LDA P_TCB_VISIBLE
MOVD1 A
LDA TCB_LENGTH
IMULA D2// D2: index for a new task
ADDD1 A// D1: Block for Visible Reg of a new Task
MOVB D1
CLRX
LDCTX@%-3// Resotre iRTN, iPSR, iSP from TCB
BLKMOV@*D0 @*D1// Block copy from D1 to D0 (C: counter)
JMPIH_RTN
P_TCB_STARTBOXTCB_START
P_TCB_CTXBOXTCB_START+1
P_TCB_VISIBLEBOXTCB_START+4
TCB_LENGTHBOX13
TCB_START
TCB0BOX0// State - 0:Ready, 1:Wating, -1:Finished
TCB0_PCBOXIO_BOUND_TASK// REC_ADD
TCB0_PSRBOX0
TCB0_SPBOXU(5000)// Segment 4
TCB0_D3BOX0// TID로 사용(편의상 D3는 없는 것으로 한다)
TCB0_OTHER_REGRESBOX8// D2,D1,D0,C,B,R,X,A
TCB1BOX0// State - 0:Ready, 1:Wating, -1:Finished
TCB1_PCBOXCPU_BOUND_TASK
TCB1_PSRBOX0
TCB1_SPBOXU(6000)// Segment 5
TCB1_D3BOX1// TID로 사용(편의상 D3는 없는 것으로 한다)
TCB1_OTHER_REGRESBOX8// D2,D1,D0,C,B,R,X,A
////////// User Segment //////////
ORGBEGIN_USER1
IO_BOUND_TASK
SGMTSEG_ON_ALL/1000// Turn on all 7 segment displays
LDA SEG_ON_ALL
SGMTMMIO_SEG_CMD/1000
STA MMIO_SEG_CMD
SGMT
CLRX
LOOP1
LDA @MSG_TABLE// request DMA IO
SGMTMMIO_SEG_DMASRC/1000
STA MMIO_SEG_DMASRC
CLRA// 7segment 장치의 buffer 주소는 0에서 시작
STA MMIO_SEG_DMADST
SGMTMSG_LENG/1000
LDA MSG_LENG
SGMTMMIO_SEG_DATA/1000
STA MMIO_SEG_DATA
LDA SEG_DMA_WRITE
STA MMIO_SEG_CMD
SGMT
WAIT_LOOP1SETRTNNEAR NEXT_IO
INT5// check dma flag
INT1// Yield
JMPWAIT_LOOP1
NEXT_IO
INCX
LDA COUNT
CMPA X
SKZ
JMPLOOP1
INT2// Finish
SGMTIDLE_TASK/1000
JMPIDLE_TASK// Goto Idle Task
COUNTBOX4
MSG_LENGBOX10
MSG_TABLEBOXMSG0
BOXMSG1
BOXMSG2
BOXMSG3
BOXMSG4
BOXMSG5
BOXMSG6
BOXMSG7
BOXMSG8
BOXMSG9
MSG0BOX0b00111111//0
MSG1BOX0b00000110//1
MSG2BOX0b01011011//2
MSG3BOX0b01001111//3
MSG4BOX0b01100110//4
MSG5BOX0b01101101//5
MSG6BOX0b01111101//6
MSG7BOX0b00000111//7
MSG8BOX0b01111111//8
MSG9BOX0b01101111//9
BOX0b01000000//-
BOX0b01000000//-
BOX0b01000000//-
BOX0b01000000//-
BOX0b01000000//-
BOX0b01000000//-
BOX0b01000000//-
BOX0b01000000//-
BOX0b01000000//-
BOX0b01000000//-
BOX0b01000000//-
////////// User Segment //////////
ORGBEGIN_USER2
CPU_BOUND_TASK
SGMT// set PSR to current segment
// SP는 OS가 TCB를 초기화할 때 설정한다.
CLRB// LD B #0
DECSP// room for return value of MAIN
SETRTNNEAR RTN0// CALL MAIN
PUSHR
JMPMAIN
RTN0
INT2// Finish
SGMTIDLE_TASK/1000
JMPIDLE_TASK// Goto Idle
MAINPUSHB
MOVB SP
PUSHALL// save visible registers
DECSP// room for return value of F_RECADD
INIO_BRIDGE
PUSHA// pass parameter, (n)
SETRTNNEAR RTN1// CALL F_RECADD
PUSHR
JMPF_RECADD
RTN1INCSP// remove used arguments
POPA// get return value
OUTIO_BRIDGE
POPALL// restore visible registers
MOVSP B
POPB
POPR// RETURN
JMP*R
F_RECADDPUSHB// PUSH B
MOVB SP// MOV B SP
DECSP// room for local variable
PUSHALL// save visible registers
LDA %2// get parameter
CLRC
CMPA C// if (n==0)
SKZ
JMPELSE
LDA #0// return 0;
STA %3// put return value
POPALL// restore visible registers
MOVSP B
POPB
POPR// RETURN
JMP*R
ELSE
DECSP// room for return value of F_RECADD
// INT1// No Yield, 인터럽트가 발생하지 않으면 끝까지 실행
LDA %2// get n
DECA// n-1
PUSHA// pass parameter
SETRTNNEAR RTN2// CALL F_RECADD
PUSHR
JMPF_RECADD
RTN2INCSP// remove used arguments
POPA// get return value, recadd(n-1)
ADDA %2// recadd(n-1) + n
STA %-1// r = …
LDA %-1// return r;
STA %3// put return value
POPALL// restore visible registers
MOVSP B
POPB
POPR// RETURN
JMP*R
END

Comments