Lab & Homeworks‎ > ‎

Homeworks 2012

1. Sum(1..n) 프로그램

n 값을 입력 받아 1 부터 n 까지의 합을 구해 출력하는 프로그램을 LMC 10개의 명령어를 이용하여 작성하고 실행하시오.

<< 리포트 내용 >>
  1. LMC 기계어로 작성된 프로그램에 니모닉 및 주석을 단 프로그램 (예:  299   STA 99  // A 값을 99번지에 저장, 99번지는 int n;를 뜻함)
  2. 해당 프로그램을 LMC 머신에서 실행시키는 과정을 설명 (프로그램을 메일박스로 옮기는 과정. 예: Tape booting ...)
  3. 0-9까지 10개의 명령어를 완성하기 위해 추가한 C 코드 조각에 대한 개념 설명 
  4. 생각해보기
  • 상수 1과 변수 n을 메일 박스의 어디에 배치할 것인가?
<<제출 방법>>
  • 사이버캠퍼스(http://cyber2010.kookmin.ac.kr/index.jsp)에 온라인으로 제출하고 마감일 강의 시작 전에 출력물 제출

2. LMC Op Code 개인화

1. LMC OP Code를 개인화 하시오. 
바꿀 화일: builtin/cpubuiltin.h
참고 문서: "LMC 명령어 확장하기", "모듈-> CPU -> Instruction Set -> Instruction Format"

2. 다음 프로그램을   0-9 명령어를 사용하지 말고 확장된 명령어들로 다시 작성하여 실행 하시오. 
  • IN, OUT은 예외
  • IN, OUT은 1BOX 단위로 입출력하지만 확장된 명령어는 2BOX 단위로 읽고 쓰는 것에 주의
  • 상수 및 변수는 2개의 BOX로 표현해야 한다. (낮은 자리가 낮은 주소로.. )
예    90:  DBOX  12345678  ==> 90: 5678,  91:1234
//positive difference of two numbers
IN    10
STA   11
IN    10
STA   12
SUBA  11
SKN
JMP   09
LDA   11
SUBA  12
OUT   12
COB
BOX   0
BOX   0

3. Sum(1..n) 프로그램을 0-9 명령어를 사용하지 말고 확장된 명령어들로 다시 작성하여 실행 하시오.
예: LDA 99  --->  LD  A  0099  0000  // 8자리주소는 낮은 자리가 먼저 옴

<< 리포트 내용 >>
  1. 개인화한 코드 테이블 ( builtin/cpubuiltin.h 의 build_builtin_opmap() )
  2. 바뀐 2번 프로그램(니모닉, 기계어, 주석 포함)- 예 LD  A  20    1100 0020 0000   // 20:21번지 값을 A로 이동
  3. 바뀐 Sum(1..n) 프로그램(니모닉, 기계어, 주석 포함)
  4. Sum(1..n)과 가장 유사한 C 프로그램 (상수 및 변수들 유의)
  5. 생각해보기
  • Skip on Condition & JMP의조합을 어떤 Conditional Jump로 바꿀 것인가?
  • LMC로 작성된 Sum(1..n) 프로그램의 상수, 변수들이 C 코드에서는 무엇이었을까?

<<제출 방법>>
사이버캠퍼스(http://cyber2010.kookmin.ac.kr/index.jsp)에 온라인으로 제출하고 마감일 강의 시작 전에 출력물 제출


3. Subroutine 만들기

1. Sum(1..n) 프로그램을 3개의 함수로 나누고 main에서는 이  3개 함수를 호출하는 구조로 바꾸시오.

main() {
    n=data_in();
    total = sum(n);
    print(total);
}

2. Sum(1..n) 프로그램을 Booting 할 때 로드하지 말고 Monitor에서 로드하여 실행하시오.
cassette/BOOT의 내용을 다시 아래처럼 바꾸고 Monitor의 Load 명령을 이용

     9710        // INT 10     Trap to Monitor
     0700        // COB

3. Sum(1..n)의 입출력을 Tape device에서 읽고 쓰도록 변경하시오.
참고:Text Book Ch7.8, p244, 
힌트: Tape 장치는 초기화 되어야 읽거나 쓸 수 있는데 TIO가 초기화 역할도 한다. Text Book p250
         따라서 프로그램 앞부분에 TIO 50, TIO 60을 추가 한다. (50, 60이 일고 쓸 Tape의 주소일 때)

<< 리포트 내용 >>
1. 위의 1~4 의 과정을 통해 재구성된 Sum(1..n) 프로그램 (니모닉과 주석으로 표현)
2. 새 Sum(1..n)프로그램을 C로 표현
3. 새로 구성된 Sum(1..n)을 실행시키기 까지의 과정
부팅 설정 (cassette/BOOT, CMOS 등)
Monitor 에서 로딩
입력/출력할 카세트 준비
출력 카세트 내용 확인
4. 생각해보기
자신이 작성한 Sub(1..n)을 C로 표현할 때 상수, 변수, 파라미터, 반환값 등은 어떻게 매핑되는가?

<<제출 방법>>
사이버캠퍼스(http://cyber2010.kookmin.ac.kr/index.jsp)에 온라인으로 제출하고 마감일 강의 시작 전에 출력물 제출

4. Instruction Set 선택(40개)

1. Instruction Set의 "선택" 69개 중 40개를 선택
2. 이 40개의 Instruction 만을 이용해서 다음 프로그램을 번역한다. 
Text Book CH 6.5 High Level Logic Structure 참조 p168
Assembly Language Operator들 참조: 관련된 페이지 --> 튜토리얼 --> 보다 상세히 시작하기 --> LMC 어셈블러
예제 참조: 예제 --> GRAPH.lmc

short int table[10];
char mark='*';
int i, j;
short int c, total;

main() {
for(i=0; i<10; i++) {
     table[i] = (short int)getc(stdin);    // use IN 10
     }

i=0;
c=table[i];
while(i<10 && c>0) {
    total += c;
    putc((char)c,stdout);       // use OUT 12
    putc(':',stdout);                // use OUT 13
    for(j=0; j<c; j++) {
        putc(mark,stdout);    // use OUT 13   ; 스크린에 *표가 문자로 출력됨
                                        //  Text Device of Screen p247, 
        }
    putc('\n',stdout);
    i += 1;
    c=table[i];
    }
printf("Total:");                //  LMC 어셈블리 언어 의사 명령어 사용
putc((char)total,stdout);    // use OUT 12
putc('\n',stdout);
}
3. LMC Monitor의 어셈블러 사용하기
1) CMOS를 다음 내용으로 변경한다.
 
#IRQ.No IO.Addr Type    R/W     Opt.
0       10      KEYBOARD
1       12      SCREEN
3       30      TAPE            root=cassette cassette=BOOT
4       40      TAPE            root=cassette cassette=target.bl
5       50      TAPE            root=cassette cassette=042_extended.lmc
6       60      TAPE            root=cassette cassette=target.txt

2) cassette/BOOT가 다음 내용인지 확인
 
9710        // INT 10  - trap to Monitor
0700        // COB

3) ./lmc 를 실행하여 Monitor를 실행
4) Dump CMOS로 CMOS내용 확인
 
Monitor> dc
     DEV 0 10 KEYBOARD RO : status=0010(ETOB)
     DEV 1 12 SCREEN   WO : status=0010(ETOB)
     DEV 2    Not Installed
    *DEV 3 30 TAPE     RW : status=1011(ETOB)
                            root=cassette,cassette=BOOT
    *DEV 4 40 TAPE     RW : status=0001(ETOB)
                            root=cassette,cassette=target.bl
    *DEV 5 50 TAPE     RW : status=0001(ETOB)
                            root=cassette,cassette=042_extended.lmc
    *DEV 6 60 TAPE     RW : status=0001(ETOB)
                            root=cassette,cassette=target.txt
     DEV 7    Not Installed
     DEV 8    Not Installed
     DEV 9    Not Installed

5) 어셈블링
Monitor> asm 5 4 6          // 5번 장치의 소스 코드를 번역하여 6번에 기계어 7번에 리스트를 출력
6) 로딩
Monitor> Load BL 4          // 4번 장치에서 BL 타입의 기계어를 읽어들임
7) 실행
Monitor> Run 0                // 소스 프로그램의 시작을 0번지(ORG 0)로 하였으므로 0번지로 Jump
8) 결과
0020         // TABLE에 1이 20개 들어 있고 이를 모두 합하였으므로 ...
9) target.txt, target.bl의 내용 확인
Monitor> quit   ./lmc를 종료하고 cassette 디렉토리로 이동해서 cat 명령으로 확인
또는 eclips에서 확인

<< Report 내용 >>
1. 40개의 Instruction Set (Table에 O 표시)  <-- 이 내용 다시 포함
2. 번역된 프로그램 (40개의 Instruction만 이용)
 - 모니터의 어셈블러를 이용해서 나온 어셈블리 리스트(기계어, 주소, 라인넘버, 니모닉이 다 포함) 제출
3. 실행 예시 화면

<<제출 방법>>
사이버캠퍼스(http://cyber2010.kookmin.ac.kr/index.jsp)에 온라인으로 제출하고 마감일 강의 시작 전에 출력물 제출

5. Function, Parameter passing & Return value

1. 다음 프로그램을 개인화한 40개 LMC 명령어로 번역하여 실행하시오.

int table[10];      // int 는 2 BOX짜리임
char mark='*';
int i, j, k;
int n, total, value;

insert_table(int max) {

for(i=0; i<max && i<10; i++) {
     printf{"Data ? ");                    // 끝에 '\n' 출력하지 않음
     table[i] = INPUT(stdin);          // Memory mapped IO 이용하여 2 BOX integer 입력
     }
}

draw_bar(int len) {

 OUTPUT(len,stdout);           // Memory mapped IO 이용하여 2 BOX integer  출력
 putc(':',stdout);                
 for(j=0; j<len; j++) {
        putc(mark,stdout);   
        }
 putc('\n',stdout);
}

cal_total() {

i=0;
n=table[i];
while(i<10 && n>0) {
    total += n;
    draw_bar(n);
    i += 1;
    n=table[i];
    }
 return total;
}

main() {

printf("Number of data ?");       // BIOS Macro 이용
k=INPUT(stdin);                       // Memory mapped IO 이용하여 2 BOX integer 입력

insert_table(k);
value = cal_total();

printf("Total:");                //  LMC 어셈블리 언어 의사 명령어 사용
OUTPUT(value,stdout);
putc('\n',stdout);
}


<< Report 내용 >>
1. 번역된 프로그램 (40개의 Instruction만 이용)
 - 모니터의 어셈블러를 이용해서 나온 어셈블리 리스트(기계어, 주소, 라인넘버, 니모닉이 다 포함) 제출
2. 실행 예시 화면 - 여러가지 경우

<<제출 방법>>
사이버캠퍼스(http://cyber2010.kookmin.ac.kr/index.jsp)에 온라인으로 제출하고 마감일 강의 시작 전에 출력물 제출

6. Bootstrap Loader

1. 다음 프로그램을 LMC 코드로 번역하여 BL type의 실행화일을 처리하는 Absolute Loader를 제작하시오.

#define BOOT_DEV_ADDR  30    // 시스템 차원에서 고정 시키기로 한다.
char progname[10];
int i, length, exec_start;
int *start;

main() {
read Header record, if it is not H record, error!
asm {
BLK.SZ 10
LD.CW progname,  BOOT_DEV_ADDR
}
start = atoi(asm { LD A 92000000+BOOT_DEV_ADDR*10});
length = atoi(asm { LD A 92000000+BOOT_DEV_ADDR*10});

for (i=0; i<length; i++) {
        *start[i] = asm{ IN BOOT_DEV_ADDR };
};
read End record, if it is not E record, error!
get exec_start from E record;
printf("Program %s is started ...\n",progname);
jump to exec_start;  
}

2. 1번 프로그램의 실행화일을 4번 장치에 넣고 Monitor로 로딩한 다음 3번 장치를 30번지로 지정하고 그 장치에 임의의 BL type실행화일 카세트를 장착하여 실행해본다. 이 때 3번 장치에 있던 BOOT 카세트는 Monitor의 CC(Change Cassette) 명령에 의해 실행하려는 것으로 바뀌어야 한다.

3. Starter 만들기 - 
예제: rom3.lmc를 복사해서 다음 부분을 바꿔서 실행해 보시오.
1) START 0 로 변경
2) 프롬트를 "Monitor>" 대신 자신의 것으로 변경

4. 2번에서 만든 Starter를 2000번지에 로드해서 그 이미지를 BL type으로 받으시오
dump 2000 <length>  <dev #>

5. mkboot는 2개의 BL type 살행화일을 하나의 테입으로 합하여 주는 명령이다. 이 때 첫번째 프로그램은 100박스로 끊거나 100까지 0을 채워 주는데 ROM 로더가 인식하는 포맷으로 바꾸어 주고 그 뒤로는 BL type의 실행화일을 이어서 추가해준다. 따라서 위의 1번에서 만든 Absolute loader를 BL type으로 어셈블하고 4번에서 Starter의 BL type 이미지를 가지고 새로운 BOOT 카세트를 만들어 이를 가지고 부팅해 보시오. 자신의 Starter가 실행되어야 한다.
 

<< Report 내용 >>

1. Absolute Loader 및 Starter 프로그램 
 - 모니터의 어셈블러를 이용해서 나온 어셈블리 리스트(기계어, 주소, 라인넘버, 니모닉이 다 포함) 제출
2. 실행 예시 화면 - 여러가지 경우
 
 
<<제출 방법>>
사이버캠퍼스(http://cyber2010.kookmin.ac.kr/index.jsp)에 온라인으로 제출하고 마감일 강의 시작 전에 출력물 제출
 
7. Activation Record

1.  다음 프로그램을  LMC 코드로 바꾸어 실행하시오.

static int table[10] = {10,9,8,7,6,5,4,3,2,1};    // 이렇게 초기화가 된다고 가정!!
static int a, b, result;
static int *p;

static int add_two(int x, int y) {
    int tmp;
    tmp = x + y;
    return tmp;        // 반환값을 A 레지스터가 아닌 스택을 통해서 전달 받는다. 

    }

main() {
    result = add_two(2,3);
    OUT(result,stdout);

    a = table[2];
    b = table[3];
    result = add_two(a,b);
    OUT(result,stdout);

    result = add_two(table[4],table[5]);
    OUT(result,stdout);

    p = table;
    result = add_two(p[1], *(p+2));
    OUT(result,stdout);

    p = &table[5];
    result = add_two(p[1], *(p+2));
    OUT(result,stdout);
}

8. Activation Record - Local Array Variable

1.  다음 프로그램을  LMC 코드로 바꾸어 실행하시오.



static int add_two(int x, int y) {
    int tmp;
    tmp = x + y;
    return tmp;        // 반환값을 A 레지스터가 아닌 스택을 통해서 전달 받는다. 

    }

main() {

    int table[10];  
    int a, b, result;
    int *p;
    int i;

    for(i=9; i--; i>=0)
         table[i] = i+1;

    result = add_two(2,3);
    OUT(result,stdout);

    a = table[2];
    b = table[3];
    result = add_two(a,b);
    OUT(result,stdout);

    result = add_two(table[4],table[5]);
    OUT(result,stdout);

    p = table;
    result = add_two(p[1], *(p+2));
    OUT(result,stdout);

    p = &table[5];
    result = add_two(p[1], *(p+2));
    OUT(result,stdout);
}
 

 9. Exception Handler

 1. 다음 두개의 프로그램을 BL type의 실행 코드로 만들고 mkboot 명령으로 하나의 BOOT 카세트를 제작하시오. 이 때 Starter:Kernel 은 2000번지에 로드한뒤 dump하는 방법으로 BL type으로 변환 가능하다.
 
 
                << Bootstrap Loader>>
                START   0
                LD         A #30          // Boot 장치의 IO 주소를 A에 넣기
                JUMP    90090000U  // 내장 Bootstrap Loader로 점프
                END
 << Starter:Kernel >>
 
KERNEL  START   2000
 
RAM_IVT            EQU    900000000U
IV_EH_ENTRY    EQU   RAM_IVT
IV_EH_RETURN  EQU  RAM_IVT+2
IV_SSP              EQU  RAM_IVT+4
  
                USE     TEXT
ENTRY     MOV     A,  #EH_ENTRY
                MOV     IV_EH_ENTRY, A
                MOV     SP, #STK_BTM
                MOV     B,  #0
                JUMP    MY_MONITOR 
                USE     DATA
                USE     BSS
 
                USE     STACK
HEAP       RESDBOX 400
STK_BTM    EQU     $
 
IH             EQU 90030000U
EXR         EQU 90030010U
TRH         EQU 90030020U
                USE     TEXT
EH_ENTRY        
                INTOFF
                PUSHALL
                LDIRQ                         // X: Exception Source, A: Reason
                CMP     X, #10             // if( source < 10 )
                JN      IH                       //    jump IH(Interrupt Handler)
                JZ      EXR                   // else if( source == 10 )
                                                   //    jump EXR(Exception Routine)
                
MY_TRH
                CMP     A, #90            // if( reason != 90 )
                JNE      SYS_CALL     //    jump SYS_CALL(next case)
                MOV     X, #-4            // else return to KERNEL
                MOV     A, #ENTRY       // Go to KERNEL
                MOV     *@IV_SSP, A
                POPALL
                JUMP    *IV_EH_RETURN
 
SYS_CALL
                CMP     A, #80           // System call !!
                JNE      GO_TRH
                << printf("D register has %d",D); >>  // D register 값을 출력
                POPALL
                JUMP    *IV_EH_RETURN
 
GO_TRH  POPALL
                JUMP    TRH             //  jump TRH(Builtin Trap Handler)

 
M_PROMPT         EQU 30
M_QUIT                EQU 31
M_LOADDEV        EQU 32
M_LOADBL          EQU 33
M_LOADRL          EQU 34
M_LOADLL          EQU 35
M_LOAD              EQU 36
M_MOVE              EQU 37
M_RUN                 EQU 38
M_DUMP_CMOS  EQU 39
M_DUMP              EQU 40
M_ASM                EQU 41
M_DASM             EQU 42
M_INTERPRET    EQU 43
M_HELP              EQU 44
M_CC                  EQU 45
M_CAT                EQU 46
M_MKBOOT        EQU 47
M_VIEWBL          EQU 48
M_VIEWRL          EQU 48
M_VIEWLL           EQU 48
 
USE        BSS
BUFFER    RESBOX    100
 
USE        TEXT
MY_MONITOR
        
                // ROM3의 Monitor 를 switch문으로 전환한 것
                

                 INTON
PROMPT  LD   A , #BUFFER 
                 LD   X, #=C'My Monitor' // PROMPT 주소  
                                    // Prompt 변경할 것
                 INT  M_PROMPT

                LD        D,  #BUFFER
                PUSH   D

CASE_QUIT
                CMP    A, #M_QUIT
                JNE      CASE_LOADDEV
                POP    A
                INT      M_QUIT
                JUMP   END_CASE

CASE_LOADDEV
                CMP    A, #M_LOADDEV
                JNE      CASE_LOADBL
                POP    A
                INT       M_LOADDEV
                JUMP    END_CASE

CASE_LOADBL
                CMP    A, #M_LOADBL
                JNE     CASE_LOADRL
                POP    A
                INT      M_LOADBL
                JUMP   END_CASE

CASE_LOADRL
                CMP    A, #M_LOADRL
                JNE     CASE_LOADLL
                CALL   MY_LOAD_RL            // 자신의 LOAD RL이 구현되었다면 이를 호출
                JUMP   END_CASE
                . . . . 


END_CASE
                 ADD    SP, #2
                 JUMP   NEAR PROMPT


MY_LOAD_RL
                PUSH    B
                MOV      B, SP
                    
                    // 자신이 구현한 loader

                RET

                END     ENTRY
 
2. 위에서 만든 BOOT 카세트로 부팅을 하여 Starter:Kernel이 실행되게 하고 여기서 다음 프로그램을 실행 시키시오.
 
TEST        START  0
               MOV     D, #1
               INT        80
               MOV     D, #2
               INT        80
 
               INT        90
               COB
               END
 
3. BOOT 카세트로 부팅해서 2번 프로그램을 실행하는 과정을 모두 설명하시오.
 
Comments