이 블로그는 임베디드 컴퓨터를 이용한 장치(시스템) 개발과 원격제어에 필요한 지식을 공유 하기 위한 블로그 입니다.
실제 개발과 프로그램 예를 위하여 Microchip 사의 ATmega128를 사용한 보드와 Arduino Mega 보드(ATmega2560), Raspberry Pi, Raspberry Pi Pico, WiFi 모듈을 사용 합니다.

avr-asm-programming-basic

Assembly Language Programming Basic
  Assembly Language Programming Basic



  • Assembly Language Coding Techniques
    • Assembly Language Program의 구조
      • 프로그램을 읽기 쉽고 디버깅(Debugging)을 용이하게 하기 위하여 Code를 적절한 구조로 배치하는 것이 중요하다. 아래 예는 대표적인 Code 배치 예 이다.
      • Code 배치 예
        Header Comments
        Definition Includes

        Register Renaming

        Constant
        Declaration
        Interrupt Vectors

        Initialization Code
        Main Code


        Subroutines

        ISRs

        Data

        Additional Code
        Includes
        설 명
        제목(Title), 저자(Author), 날짜 및 설명
        특정 Device를 사용하기 위한 Includes 파일.
        예: "m128def.inc"
        프로그램을 이해하기 쉽게하기 위한 Register 이름 변경 및 변수 생성 등.
        예: .def tmp = r0
        프로그램 작성에 필요한 상수 선언 과 생성.
        예: .equ addr = $2000 Declaration
        Interrupt Vectors Table

        모든 초기화 코드. 예: Stack pointer, 전역변수 등
        사용자 프로그램


        프로그램에서 사용되는 Subroutines

        Interrupt Subroutines

        전역변수 등의 초기화에 필요한 데이터.
        예: .DB “hello”
        만약 추가로 필요한 source code기 있는 경우 이 곳에 Includes 한다.


    • Register Naming
      • DEF 지시문(Directive)을 사용하여 레지스터에 기호 이름을 설정한다.
      • DEF 지시문을 사용하여 새로운 이름으로 정의된 레지스터는 새로 정의된 이름(기호)을 사용하여 참조할 수 있다.
      • DEF 지시문을 사용하여 레지스터를 알기 쉬운(프로그램에서 의미 있는)기호로 정의하면 프로그램의 이해와 디버깅(Debugging)이 용이해 진다.
      • DEF 지시문을 사용하여 정의된 레지스터의 이름은 나중에 다른 이름으로 제 정의 할 수 있다.
      • 레지스터 이름은 가능한 짧고, 프로그램에서 의미 있고, 고유해야 한다.
      • DEF 지시문을 사용하여 레지스터 이름을 재 정의하는 예

    • Constants 와 Addressing
      • 같은 상수(Constants) 값을 반복하여 사용하는 경우 상수에 의미 있는 이름을 부여하여 상수를 사용하는 것이 유용하다.
      • 레지스터 이름과 같이 상수 이름도 가능한 짧고, 프로그램에서 의미 있고, 고유해야 한다.
      • 상수에 의미 있는 이름을 부여하면 코드를 더 읽기 쉽게하여 프로그램의 이해와 디버깅을 쉽게 한다.
      • 상수를 프로그램 앞 부분에서 이름을 사용하여 정의하면 프로그램에 반복 사용한 상수 값을 변경하여야 하는 경우 상수의 정의만 변경하면 된다. 만약 반복하여 여려번 프로그램 내에서 직접 상수 값을 사용하였으면 모든 상수 값을 변경하여야 한다.
      • 메모리 주소(16 Bits)를 상수로 사용하는 경우
        • 상수의 일반적인 용도는 주소(16-bit constant)를 설정하는 것이다.
        • Registers(8-bits)에 주소(16-bit constant)를 저장하는 경우 Rg에 주소의 상위(High) Byte와 하위(Low) Byte를 나누어 저장하여야 한다.
        • 16-bit 상수를 상위(High) Byte와 하위(Low) Byte를 나누어 정의 하는 경우 예
        • 이 예에서는 16 Bits 주소가 2개의 이름으로 분리되어 전체 주소를 쉽게 알 수 없다.

        • 16-bit 상수를 직접 정의하고 HIGH, LOW Macro function을 사용하여 Rg에 Load 하는 예
        • 이 예에서는 16 Bits 주소 값을 쉽게 알 수 있다. 이 예가 윗 예보다 Code를 읽기 좋다.


    • ATMega128 Definition File
      • Definition File은 특정 칩셋 내의 공통 I/O 레지스터(Rg) 및 특수 레지스터에 대한 주소와 값을 알기 쉬운 이름으로 정의한 Include 파일이다.
      • 칩셋에 따라 공통 I/O 레지스터(Rg), 특수 레지스터 등의 주소가 다르기 때문에 칩셋에 따라 다른 Definition File이 필요하다.
      • 칩셋에 따라 공통 I/O 레지스터(Rg), 특수 레지스터 등의 주소가 다른 경우에도 동일한 기능을 하는 Rg의 이름을 동일하게 정의하면 서로 다른 칩셋을 사용하는 경우에도 칩셋에 따른 Definition File을 Include 하여 프로그램 변경을 최소화 할 수 있다.
      • ATMega128을 위한 Definition File(m128def.inc) 예
      • 주: 위 예는 m128def.inc의 일부를 편집한 예이다. m128def.inc 파일의 위치는 아래 경로 예와 같다. m128def.inc 파일은 Text 파일이기 때문에 Text 편집기를 사용하여 확인할 수 있다. 그러나 이 파일은 중요한 시스템 파일이기 때문에 임의로 변경되지 않도록 주의하여야 한다.

      • m128def.inc 파일의 경로 예
      • C:\Program Files (x86)\Atmel\Studio\7.0\packs\atmel\ATmega_DFP\1.6.364\avrasm\inc\m128def.inc

      • m128def.inc 파일에는 ATMega128 프로그래밍에 필요한 상수가 .equ 와 .def 지시문(Directive)을 사용하여 정의되어 있다.

    • Interrupt Vector Table
      • ATmega128의 하드웨어에서 인터럽트(Interrupt)가 발생(Trigger)하면 자동으로 특별한 함수(Interrupt service routine)를 호출한다.
      • 전체 인터럽트는 SREG의 비트 7(Global Interrupt Enable Flag)를 사용하여 활성화(Enable) 또는 비활성화(Disable)한다.
      • SEI(Set Global Interrupt) 과 CLI(Clear Global Interrupt) 같은 AVR Assembly 명령을 사용하여 Global Interrupt를 활성화(Enable) 또는 비활성화(Disable) 한다.
      • 특정 장치의 Interrupt를 사용하기 위하여는 Global Interrupt를 활성화(Enable)하고 또한 특정 장치의 Interrupt를 활성화(Enable) 하여야 한다.
      • 인터럽트가 트리거(Trigger)되면 현재 명령 주소가 스택에 저장되고 Interrupt Vectors Table에 설정된 주소(Interrupt service routine의 주소)로 프로그램이 이동 하게 된다.
      • Interrupt service routine이 종료되면 스택에 저장된 현재 명령 주소를 이용하여 현재 실행하된 프로그램을 계속 실행한다.
      • Interrupt Vectors Table은 특정 장치의 Interrupt이 발생한 경우 실행되는 Interrupt service routine의 주소가 저장된 Table이다.
      • Interrupt를 사용하는 프로그램에서는 Interrupt Vector Table에서 Interrupt Vector(Interrupt service routine의 주소)를 설정하여야 한다.
      • 참고자료: Interrupt 이해를 위한 참고자료 "ATMega128 External Interrupt"

      • 아래 예는 ATMega128 Interrupt Vector Table의 예 이다. 이 Table에는 RESET Interrupt Vector만 설정되어 있다.
      • ATMega128 Interrupt Vector Table의 예: "avr128_interrupt_table.inc"


    • Assembly Language Program을 위한 Template: "avr128_template.asm"
      • 아래 예는 Assembly Language Program을 위한 Template 예 이다. 각자의 필요예 따라 아래 예를 참고하여 적당한 Template를 작성하여 사용할 수 있다.

    • Template를 이용한 Assembly Language Program 예
      • 아래 예는 위 Template를 복사하여 작성한 Assembly Language Program 예 이다.
      • DSEG에 Global variable(data_x, data_y, data_z)을 설정하고, 변수(data_x, data_y)를 초기화하고, Subroutine에서 두 변수의 값을 읽어 Add 한 다음 변수(data_z)에 Write 하는 프로그램 예 이다.
      • 프로그램 편집하기
        • Interrupt를 사용하지 않는 경우 ".include "avr128_interrupt_table.inc"을 Comment 처리 또는 삭제한다. 이 예에서는 RESET(전원이 처음 인가되는 경우 또는 Reset SW를 누르면 실행되는 Interrupt) Interrupt를 사용한다.
        • 레지스터에 기호 이름을 재 설정(사용하지 않는 Rg 정의는 삭제하고 사용하는 Rg는 프로그램 내용에 적합하게 재 정의)한다.
        • Program Constants을 재 설정(사용하지 않는 상수의 정의는 삭제하고 사용하는 상수는 프로그램 내용에 적합하게 재 정의)한다.
        • DSEG에 전역변수를 재 설정(사용하지 않는 전역변수의 정의는 삭제하고 사용하는 전역변수는 프로그램 내용에 적합하게 재 정의)한다.
        • CSEG에 필요한 사용자 프로그램을 작성한다.
      • 실험을 위한 준비
        • Microchip Studio를 실행하고 실험에 사용할 Project를 생성한다.
        • Debugging에 사용할 Simulator를 설정한다.
        • 프로그램 편집 창(main.asm)에 위 Code를 복사하고 저장한다.
        • 위 Interrupt Vector Table 절에서 Interrupt Vector Table을 복사하여 main.asm 가 있는 폴더에 "avr128_interrupt_table.inc" 파일을 만든다.
      • 실험 방법
        • 참고자료: "Debugger를 이용한 Instruction Set과 Microprocessor의 이해"

        • Start Debugging and Break(Alt+F5) 명령을 실행하고, Debugger 가 실행되면 Debugging에 필요한 Processor Status 창과 Memory 창이 열려있는지 확인한다.
        • Memory 창의 memory 선택 Box에서 dataIRAM을 선택하면 Address Box에 0x0100,data(DSEG의 100번지 부터 Memory 창에 표시됨) 가 표시된다.
        • Step Into(F11) 명령을 실행하며 "Processor Status 창"의 내용(Stack Pointer(0x10FF), Z Rg, Y Rg, r16, r17, Call 명령과 ret 명령 결과)과 Memory 창의 내용(data_xi(0x0100 - 0x0103 번지))이 예상하는 프로그램 결과와 일치하는지 확인한다.
        • 주: Call 명령이 실행될 때 Program Counter 값의 변동과 Return 번지가 Stack에 바르게 저장되는지 확인한다. 또한 ret 명령에 따른 Program Counter 값과 Stack Pointer의 값이 예상한 결과와 일치하는지 확인한다.


  • Flow Control
    • 프로그램의 흐름을 제어하는 코딩 기술을 이해하기 위하여 이 절에서는 C-like 흐름제어(Flow control)에 대하여 설명한다.

    • IF Statement
      • c 언어의 IF statement 기본형은 아래와 같다.
      • 위 예에서 expr이 True(Nonzero) 이면 statement를 실행하고 False(Zero) 이면 statement를 Skip 한다.
      • IF Statement를 사용하는 실제 Coding 예는 아래와 같다.
      • 위 c 프로그램의 Assembly 등가 버전은 아래 예와 같다.
      • 위 예에서는 Code를 간단히 하기 위하여 expr은 r16(만약 expr이 복잡한 식일 경우 식의 연산 결과를 r16에 저장여야함))을 사용하고, Statement는 간단한 inc n Instruction 만 사용하였다.

    • IF-ELSE Statement
      • c 언어의 IF-ELSE Statement 기본형은 아래와 같다.
      • 위 예에서 expr이 True(Nonzero) 이면 statement 1를 실행하고 False(Zero) 이면 statement 2를 실행한다.
      • IF-ELSE Statement를 사용하는 실제 Coding 예는 아래와 같다.
      • 위 c 프로그램의 Assembly 등가 버전은 아래 예와 같다.

    • WHILE Statement
      • WHIRE 문은 일반적으로 반복 루프를 만드는 데 사용된다. 장치를 제어하는 마이크로 컨트롤러 프로그램에서는 전원이 인가된 상태에서는 계속 장치가 동작하기 때문에 WHIRE 문을 사용하여 무한 루프를 만들 수 있다.
      • c 언어의 WHILE Statement 기본형은 아래와 같다.
      • 위 예에서 expr이 True(Nonzero) 이면 statement를 실행한다.
      • WHILE Statement를 사용하는 실제 Coding 예는 아래와 같다.
      • 위 c 프로그램의 Assembly 등가 버전은 아래 예와 같다.

    • DO-WHILE Statement
      • DO-WHIRE 문은 WHINE 문의 변형으로 루프의 맨 아래에서 조건 테스트(WHINE 문은 맨 위에서 테스트를 함)를 한다. 그렇기 때문에 DO-WHIRE에서는 DO-WHIRE 문 내에 있는 Statement를 최소 1회 이상 실행하게 된다.
      • c 언어의 DO-WHILE Statement 기본형은 아래와 같다.
      • 위 예에서 먼저 statement를 실행하고 expr이 True(Nonzero) 이면 DO-WHILE 루프를 반복한다.
      • WHILE Statement를 사용하는 실제 Coding 예는 아래와 같다.
      • 위 c 프로그램의 Assembly 등가 버전은 아래 예와 같다.

    • FOR Statement
      • FOR 문은 WHILE 문과 마찬가지로 코드를 반복적으로 실행하는 데 사용된다. FOR 문의 동작을 WHILE 문을 이용하여 설명할 수 있다.
      • c 언어의 FOR Statement 기본형은 아래와 같다.
      • WHILE 문을 사용하여 위 FOR 문과 동일한 기능을 아래와 같이 구현할 수 있다.
      • FOR Statement를 사용하는 실제 Coding 예는 아래와 같다.
      • 위 c 프로그램의 Assembly 등가 버전은 아래 예와 같다.

    • SWITCH Statement
      • SWITCH 문은 IF-ELSE 문을 일반화하는 다방향 조건부 분기문이다.
      • c 언어에서 SWITCH Statement를 사용하는 대표적인 Coding 예는 아래와 같다.
      • 위 c 프로그램의 Assembly 등가 버전은 아래 예와 같다.

    • Subroutines 과 Functions
      • Subroutines 과 Functions 개요
        • 서브루틴은 반복적으로 Call 하여 사용할 수 있는 특정한 기능을 실행하는 프로그램 모듈이다. 함수는 c 언어에서 사용하는 개념이으로 미리 약속된 방법으로 인수를 전달하고 결과를 돌려 받는 특별한 서브루틴 이다.

          참고자료: "Mixing C and assembly language programs.pdf"

        • 서브루틴(Subroutines)이나 함수(Functions)를 사용하여 프로그래머는 코드의 크기와 복잡성을 획기적으로 줄일 수 있다.
        • 서브루틴과 함수는 재사용 가능한 코드로서 동일한 코드를 프로그램 전체에서 반복적으로 사용할 수 있다.
        • 서브루틴과 함수는 메인 프로그램 외부에서 생성된 다음 메인 프로그램에서 호출되며, 때로는 여러 영역(다른 함수 등)에서 호출할 수 있다.
        • 서브루틴과 함수는 CALL, RCALL, ICALL 또는 EICALL 명령을 통해 호출되며 호출한 프로그램의 주소로 돌아가기 위해 호출 명령(CALL, RCALL, ICALL 또는 EICALL 명령)과 대응하는 RET 명령을 실행하여야 한다.
        • 서브루틴과 함수를 실행(Call)하기 위하여는 함수 또는 서브루틴의 이름을 나타내는 레이블(Label)을 사용하여야 한다.
        • 서브루틴과 함수는 Stack(Return address와 Local variable의 저장 공간으로 사용)를 사용하기 때문에 서브루틴과 함수를 실행(Call)하기 전에 Stack를 초기화 하여야 한다.
        • 서브루틴과 함수를 실행(Call)하기 위하여 필요한 Stack의 초기화
          • 서브루틴과 함수를 실행(Call)하기 전에 아래와 같이 Stack(Stack Pointer)을 초기화 하여야 한다.

            주: Stack은 High address로 부터 Low address 방향으로 Data를 저장(Push, Call 등의 명령 사용)하기 때문에 일반적으로 Stack은 Data RAM의 끝 번지(RAM’s end address)에 위치 시킨다.

      • Subroutine
        • 서브루틴은 서브루틴을 Call 한 프로그램의 실행에 영향을 미치지 않아야 한다. 따라서 서브루틴을 실행한 후에도 서브루틴을 실행하기 전 서브루틴을 Call 한 프로그램의 상태(SREG와 Rg의 상태)를 유지하여야 한다.
        • Call 한 프로그램의 상태를 유지 하기 위하여는 SREG(Status Register)와 서브루틴에서 사용하는 Rg를 서브루틴의 시작 부분에서 스택에 Push 하고, 서브루틴이 끝나기 직전에 Pop 하여야 한다. Rg의 Push 순서와 역순으로 Pop 동작을 실행 하는 것이 중요하다.
        • Type of Subroutine
          • Reentrant Subroutine
            • Subroutine이 실행 도중 Interrupting Program에 의하여 Interrupt 되어 다시 실행 하여도 언제나 올바른 실행 결과를 보장 할 수 있다.
            • Data 저장 장소로 Rg와 Stack(Local variable) 만을 사용 하여야 한다. Global variable를 사용 하여서는 안 된다.
          • Recursive Subroutine
            • 자기 자신을 call 할 수 있는 Subroutine 으로 ,
            • Data 저장 장소로 Rg와 Stack(Local variable) 만을 사용 하여야 한다. Global variable를 사용 하여서는 안 된다.
            • 당연히 Reentrant 한 routine이어야 한다.
        • Parameter Passing Techniques
          • Microprocessor 내부 Register 를 이용
            • 장점
              • 속도가 빠르다.
            • 단점
              • Hardware에 종속 적이다.
              • Passing 할 수 있는 Parameter 의 수가 제한된다.
          • Stack를 이용
            • 중간 규모의 Parameter를 전달 하는데 유리.
            • 알고리즘이 Microprocessor에 독립적이다.
          • Memory Block과 Pointer를 이용
            • Array 형태의 대규모 Data를 전달 하는데 유리 함.
        • Type of Parameter
          • Pass-by-value
            • 실제 값이 전달 된다.
            • 소 규모 데이터 전달에 유리 하다.
          • Pass-by-reference
            • Parameter List의 주소(Pointer)가 전달 된다.
            • 대규모 배열형 데이터 전달에 유리 하다.
            • 결과가 직접 해당 변수에 저장 될 수 있다.
        • Subroutine에 전달할 매개변수(Parameter)가 없는 경우 Coding 예
          • Subroutine을 main에서 call 하는 경우 main 프로그램 코딩 예
          • Subroutine 예

        • 내부 Register를 이용하여 Subroutine에 매개변수(Parameter)를 전달하는 예
          • 이 예는 Subroutine에 전달하여야 하는 매개변수(Parameter)의 수가 적은 경우 Rg를 사용하여 매개변수를 전달하고 결과를 Rg를 사용하여 되돌려 받는 예이다.
          • Array 형태의 대규모 Data는 Memory Buffer에 Data를 저장하고 Buffer Pointer와 Buffer length를 Rg를 이용하여 Subroutine에 전달하는 것이 효과적 이다.
          • 주: 이 예는 gcc c 에서 함수에 매개변수(Parameter)를 전달하고 결과를 되돌려 받는 방법과 동일하다.

            참고자료: C 프로그램과 Assembly 언어 프로그램을 Mixing한 프로그램 개발: "mixingCnAssembly.pdf"

          • Rg를 이용하여 상수 0x1234와 0x5678을 Subroutine을 전달하고 Subroutine에서 이 데이터의 합을 구하여 main에 되돌려(r25:r24 사용) 주는 프로그램 예
          • 위 예에서 add 명령의 인수 위치만 변경하면 movw 명령이 필요 없다. 그러나 이 예에서는 r25:r24를 이용 하여 결과를 Return하는 것을 강조하기 위여 movw 명령을 사용하였다.
          • 실험을 위한 준비
            • Microchip Studio를 실행하고 실험에 사용할 Project를 생성한다.
            • Debugging에 사용할 Simulator를 설정한다.
            • 프로그램 편집 창(main.asm)에 위 Code를 복사하고 저장한다.
          • 실험 방법
            • Start Debugging and Break(Alt+F5) 명령을 실행하면 Debugger 가 실행되고 Microchip Studio가 Debugging 모드로 변환된다. Debugging 모드에서는 프로그램 편집 창(main.asm)은 Debugging 모드로 변환되고 설정 상태에 따라 Debugging에 필요한 Processor Status 창, I/O 창, Memory 창, Watch 창 등이 열린다.
            • 이 예에서는 "Processor Status 창"이 필요하기 때문에 만약 이 창이 자동으로 열리지 않은 경우에는 Debug → Windows → Processor Status 명령을 실행하여 Processor Status 창을 Open 한다.
            • Step Into(F11) 명령을 실행한다. Step Into(F11) 명령을 실행하면 아래 예와 같이 "Debugging source code 창"에는 다음 실행될 Code의 왼쪽에 노랑색 화살표가 표시되고 Code 가 노랑색으로 표시된다.
            • Step Into(F11) 명령을 반복 실행하며 "Processor Status 창"에서 Program Counter 값과 SP 값, 그리고 프로그램에서 사용하는 Rg(R16, R22, R23, R24, R25)의 값이 프로그램 실행 결과와 일치하는지 확인한다.

        • Stack를 이용하여 Subroutine에 매개변수(Parameter)를 전달하는 예
          • Stack를 이용하여 상수 0x1234와 0x5678을 Subroutine을 전달하고 Subroutine에서 이 데이터의 합을 구하여 main에 되돌려(r25:r24 사용) 주는 프로그램 예
          • 위 프로그램의 실행 단계에서 Stack에 저장되는 Data는 아래 표와 같다.
            • 주: 위 표는 SREG, r22, r23의 초기값이 0x00 인 경우 이다.

            • Stack pointer의 초기값(위치)는 0x10FF 에 설정된다.
            • Subroutine에 Stack을 이용히여 전달하는 매개변수(Parameter)는 0x10FF - 0x10FC에 저장된다.
            • Call 명령이 실행될 때 Stack에 저장되는 Return Address는 0x10FB - 0x10FA에 저장된다.
            • Subroutine에서 Y Rg를 Frame pointe로 사용하기 위하여 Save한 Y Rg는 0x10F9 - 0x10F8에 저장된다.
            • r16 Rg를 임시 데이터 저장에 사용하기 위하여 Save한 r16 Rg는 0x10F7에 저장된다.
            • main 프로그램의 상태를 보존하기 위하여 Save하는 SREG는 0x10F6에 저장된다.
            • Subroutine에서 연산에 사용하는 Rg r22, r23는 0x10F5 - 0x10F4에 저장된다.
            • Stack pointer는 다음에 저장할 데이터의 번지를 저장하기 때문에 이 때 SP 의 값은 0x10F3 가 된다.
            • 이후 Subroutine을 실행하는 동인 pop과 ret 명령이 실행되고 성공적으로 프로그램을 종료하는 단계의 SP 값은 다시 0x10FF 가 된다.
            • 주: Frame Pointer(Y Rg)는 Subroutine에서 Stack에 Push되어 Passing된 인수와 Subroutine 내의 지역변수를 참조하는데 사용되는 기준번지를 저장하는 Pointer 이다.

          • 실험을 위한 준비
            • Microchip Studio를 실행하고 실험에 사용할 Project를 생성한다.
            • Debugging에 사용할 Simulator를 설정한다.
            • 프로그램 편집 창(main.asm)에 위 Code를 복사하고 저장한다.
          • 실험 방법
            • Start Debugging and Break(Alt+F5) 명령을 실행하면 Debugger 가 실행되고 Microchip Studio가 Debugging 모드로 변환된다. Debugging 모드에서는 프로그램 편집 창(main.asm)은 Debugging 모드로 변환되고 설정 상태에 따라 Debugging에 필요한 Processor Status 창, I/O 창, Memory 창, Watch 창 등이 열린다.
            • 이 예에서는 "Processor Status 창"과 Memory 창이 필요하기 때문에 만약 이 창이 자동으로 열리지 않은 경우에는 Debug → Windows → Processor Status 명령과 Debug → Windows → Memory 명령을 실행하여 Processor Status 창과 Memory 창을 Open 한다.
            • Memory 창의 memory 선택 Box에서 dataIRAM을 선택하면 Address Box에 0x0100,data(DSEG의 100번지 부터 Memory 창에 표시됨) 가 표시된다.
            • Memory 창에서 Stack 영역을 관찰하기 위하여 메모리 창에 0x10F0 번지 부터 표시 되도록 한다.
            • Step Into(F11) 명령을 실행한다. Step Into(F11) 명령을 실행하면 아래 예와 같이 "Debugging source code 창"에는 다음 실행될 Code의 왼쪽에 노랑색 화살표가 표시되고 Code 가 노랑색으로 표시된다.
            • Step Into(F11) 명령을 반복 실행하며 "Processor Status 창"에서 Program Counter 값과 SP 값, 그리고 프로그램에서 사용하는 Rg(R16, R22, R23, R24, R25)와 Stack 영역(0x10FF - 0x10F4)의 값이 프로그램 실행 결과와 일치하는지 확인한다.

        • Memory Block에 Data를 저장하고 Data Pointer를 Subroutine에 매개변수(Parameter)로 전달하는 예
          • 이 예는 Subroutine에 전달하여야 하는 Data가 많은 경우 Memory Block에 Data를 저장하고 Subroutine의 매개변수(Parameter)로 Data Pointer를 전달하는 예이다.
          • Array 형태의 대규모 Data는 Memory Buffer에 Data를 저장하고 Buffer Pointer와 Buffer length를 Rg를 이용하여 Subroutine에 전달하는 것이 효과적 이다.
          • 이 예는 8 Byte 길이의 두 정수의 합을 구하는 Subroutine를 작성하는 예이다. Data를 Memory Block에 저장하고 Data Pointer를 Subroutine을 전달한다. Subroutine에서 이 데이터의 합을 구하고 결과도 Pointer를 이용하여 직접 Memory Block에 저장한다.
          • 실험을 위한 준비
            • Microchip Studio를 실행하고 실험에 사용할 Project를 생성한다.
            • Debugging에 사용할 Simulator를 설정한다.
            • 프로그램 편집 창(main.asm)에 위 Code를 복사하고 저장한다.
          • 실험 방법
            • Start Debugging and Break(Alt+F5) 명령을 실행하면 Debugger 가 실행되고 Microchip Studio가 Debugging 모드로 변환된다. Debugging 모드에서는 프로그램 편집 창(main.asm)은 Debugging 모드로 변환되고 설정 상태에 따라 Debugging에 필요한 Processor Status 창, I/O 창, Memory 창, Watch 창 등이 열린다.
            • 이 예에서는 "Processor Status 창"과 Memory 창이 필요하기 때문에 만약 이 창이 자동으로 열리지 않은 경우에는 Debug → Windows → Processor Status 명령과 Debug → Windows → Memory 명령을 실행하여 Processor Status 창과 Memory 창을 Open 한다.
            • Memory 창의 memory 선택 Box에서 dataIRAM을 선택하면 Address Box에 0x0100,data(DSEG의 100번지 부터 Memory 창에 표시됨) 가 표시된다.
            • Step Into(F11) 명령을 실행한다. Step Into(F11) 명령을 실행하면 아래 예와 같이 "Debugging source code 창"에는 다음 실행될 Code의 왼쪽에 노랑색 화살표가 표시되고 Code 가 노랑색으로 표시된다.
            • Step Into(F11) 명령을 반복 실행하며 "Processor Status 창"에서 Program Counter 값과 SP 값, 그리고 프로그램에서 사용하는 Rg(R16, R17, R18, X, Y, Z)의 값과 Data memory(0x0100 - 0x0117)의 값이 프로그램 실행 결과와 일치하는지 확인한다.

        • Subroutine Documentation
          • 대부분의 프로그램은 Main 프로그램과 반복 사용이 가능한 다수의 Subroutine으로 구성 된다.
          • Subroutine를 효과적으로 사용하기 위하여는 아래와 같은 내용을 포함하는 잘 정리된 Documentation이 필요 하다.
            • Subroutine의 목적
            • Input / Output Parameter의 List
            • 사용 되는 Register와 Memory Location
            • Sample calling sequence를 포함하는 사용 예

      • Functions
        • Assembly Language Programming에서 함수(Functions)는 함수를 Call 하는 프로그램으로 부터 인수를 전달(경우에 따라 인수가 없을 수도 있음) 받아 처리하고 그 결과를 되돌려 주는 특별한 Subroutine 이다.
        • 함수(Functions)에 인수를 전달하는 방법은 인수의 수와 컴파일러에 따라 Register를 이용하는 방법과 Stack를 이용하는 방법이 있다. 경우에 따라 일부 인수는 Rg를 이용하고 나머지 인수는 Stack를 이용할 수도 있다.
        • 아래 참고자료에는 gcc c 프로그램에서 Assembly 함수를 Call 하는 방법과 Assembly Language로 작성된 Program 에서 C 함수를 Call 하는 경우에 대하여 설명하고 있다.
        • 참고자료: C 프로그램과 Assembly 언어 프로그램을 Mixing한 프로그램 개발: "mixingCnAssembly.pdf"


    • Assembly Language Programming Basic 관련 페이지 보기