*사용자 프로그램의 매개 변수가 3 페이지 (마지막 페이지)의 메모리의 일부를 가리키는 경우 커널이 Syscall 동안이 동일한 페이지 내에 RAM 페이지를 항상 매핑하므로 충돌이 있습니다. 따라서 사용자의 Page 3을 2 페이지 (세 번째 페이지)로 다시 옮겨 프로그램의 매개 변수에 액세스합니다. 물론, 매개 변수가 포인터 인 경우, 새로운 가상 주소를 가리키도록 수정됩니다 (즉, 포인터는 16KB에 의해 빼기 위해 포인터를 뺄 수 있습니다).
위와 같이 MMU/메모리 맵퍼가 구성되지 않은 Zeal 8 비트 OS를 Z80 기반 컴퓨터로 포트 할 수 있으려면 커널에는 menuconfig : No-MMU를 통해 선택할 수있는 새로운 모드가 있습니다.
이 모드에서 OS 코드는 여전히 메모리의 첫 16KB에 0x0000 에서 0x3FFF 에 매핑 될 것으로 예상되며 나머지는 RAM 일 것으로 예상됩니다.
이상적으로, 48kb의 RAM은 0x4000 에서 시작하여 0xFFFF 까지 올라가야하지만 실제로는 커널을 그보다 덜 기대하도록 구성 할 수 있습니다. 이를 위해서는 menuconfig 의 두 항목을 적절하게 구성해야합니다.
KERNEL_STACK_ADDR : 이것은 커널 RAM 영역의 끝을 표시하고 이름이 표시된대로 커널 스택의 바닥이됩니다.KERNEL_RAM_START : 스택, 커널 및 드라이버가 사용하는 모든 변수가 저장되는 커널 램의 시작 주소를 나타냅니다. 물론 이러한 모든 데이터를 저장하기에 충분히 커야합니다. 자세한 내용은 현재 커널 BSS 섹션 크기는 약 1KB입니다. 스택 깊이는 대상 드라이버의 구현에 따라 다릅니다. 스택에 1kb를 할당하면 (큰) 버퍼가 저장되지 않는 한 충분해야합니다. 커널 RAM에 대해 최소 3KB를 할당하는 것은 안전하고 미래를 방지해야합니다.요약하면, 여기 메모리의 사용법을 보여주는 다이어그램이 있습니다.
사용자 프로그램과 관련하여 스택 주소는 항상 실행되기 전에 커널별로 KERNEL_RAM_START - 1 로 설정됩니다. 또한 사용 가능한 주소 공간에서 사용 가능한 마지막 바이트의 주소에 해당합니다. 이는 프로그램이 SP - 0x4000 수행하여 사용 가능한 RAM의 크기를 결정할 수 있음을 의미합니다.
ld hl, 0
add hl, sp
ld bc, -0x4000
add hl, bc
; HL contains the size of the available RAM for the program, which includes the program's code and its stack.
Z80은 여러 가지 일반 목적 레지스터를 제공하며, 모두 커널에 사용되는 것은 아닙니다. 여기 각각의 범위가 있습니다.
| 등록하다 | 범위 |
|---|---|
| AF, BC, DE, HL | 시스템 및 응용 프로그램 |
| AF ', BC', DE ', HL' | 인터럽트 핸들러 |
| ix, iy | 응용 프로그램 (OS에서 사용하지 않음) |
이는 OS가 IX 및 IY 레지스터를 변경하지 않으므로 응용 프로그램에서 자유롭게 사용할 수 있음을 의미합니다.
대체 레지스터 (이름 뒤에 ' )는 인터럽트 핸들러에서만 사용될 수 있습니다 1 . 응용 프로그램은 이러한 레지스터를 사용해서는 안됩니다. 어떤 이유로 든, 당신은 여전히 그것들을 사용해야한다면, 사용되는 동안 인터럽트를 비활성화하는 것을 고려하십시오.
my_routine:
di ; disable interrupt
ex af, af' ; exchange af with alternate af' registers
[...] ; use af'
ex af, af' ; exchange them back
ei ; re-enable interrupts
시스템이 하드웨어 (타이머, 키보드, GPIO ...)에서 신호를받지 않으므로 인터럽트를 너무 오랫동안 비활성화하면 해로울 수 있습니다.
Z80은 8 개의 별개의 재설정 벡터를 제공합니다. 시스템은 항상 메모리의 첫 번째 가상 페이지에 항상 저장되므로 모두 OS에 예약되어 있습니다.
| 벡터 | 용법 |
|---|---|
| $ 00 | 소프트웨어 재설정 |
| $ 08 | SYSCALL |
| $ 10 | HL의 주소로 점프합니다 (HL 호출에 사용할 수 있음) |
| $ 18 | 사용되지 않았습니다 |
| $ 20 | 사용되지 않았습니다 |
| $ 28 | 사용되지 않았습니다 |
| $ 30 | 사용되지 않았습니다 |
| $ 38 | 인터럽트 모드 1 용으로 예약, 대상 구현에서 사용할 수 있습니다. |
사용자 프로그램이 실행되면 커널은 3 페이지의 RAM (48KB)을 할당하고 이진 파일을 읽고 실행하여 기본적으로 가상 주소 0x4000 에서 시작합니다. 이 입력 지점 가상 주소는 옵션 KERNEL_INIT_EXECUTABLE_ADDR 옵션을 사용하여 menuconfig 통해 구성 할 수 있지만, 기존 프로그램은 런타임에 재배치 할 수 없기 때문에 더 이상 다시 컴파일되지 않고 더 이상 작동하지 않습니다.
아래에 설명 된 바와 같이, exec SyScall은 실행할 바이너리 파일 이름과 매개 변수의 두 매개 변수를 취합니다.
이 매개 변수는 레지스터 DE 및 BC 통해 실행하기 위해 이진으로 복사하여 이진으로 전송 될 null-terminated 문자열이어야합니다.
DE 문자열의 주소를 포함합니다. 이 문자열은 일반적으로 스택 위에 새 프로그램의 메모리 공간에 복사됩니다.BC 해당 문자열의 길이가 포함되어 있습니다 (SO, Null-Byte 제외). BC 가 0 인 경우 DE 사용자 프로그램에 의해 폐기되어야 합니다 . 이 시스템은 SYSCALLS에 의존하여 사용자 프로그램과 커널간에 요청을 수행합니다. 따라서 이것은 하드웨어에서 작업을 수행하는 방법이 될 것입니다. 가능한 작업은 아래 표에 나열되어 있습니다.
| 숫자 | 이름 | 파라. 1 | 파라. 2 | 파라. 3 |
|---|---|---|---|---|
| 0 | 읽다 | U8 Dev | U16 BUF | U16 크기 |
| 1 | 쓰다 | U8 Dev | U16 BUF | U16 크기 |
| 2 | 열려 있는 | U16 이름 | U8 플래그 | |
| 3 | 닫다 | U8 Dev | ||
| 4 | dstat | U8 Dev | U16 DST | |
| 5 | 통계 | U16 이름 | U16 DST | |
| 6 | 구하다 | U8 Dev | U32 오프셋 | U8 |
| 7 | IOCTL | U8 Dev | U8 CMD | U16 Arg |
| 8 | mkdir | U16 경로 | ||
| 9 | chdir | U16 경로 | ||
| 10 | 커디 르 | U16 경로 | ||
| 11 | Opendir | U16 경로 | ||
| 12 | readdir | U8 Dev | U16 DST | |
| 13 | Rm | U16 경로 | ||
| 14 | 산 | U8 Dev | U8 편지 | U8 FS |
| 15 | 출구 | U8 코드 | ||
| 16 | exec | U16 이름 | U16 Argv | |
| 17 | DUP | U8 Dev | u8 ndev | |
| 18 | msleep | U16 기간 | ||
| 19 | settime | U8 ID | U16 시간 | |
| 20 | gettime | U8 ID | U16 시간 | |
| 21 | 세트 데이트 | U16 날짜 | ||
| 22 | GetDate | U16 날짜 | ||
| 23 | 지도 | U16 DST | U24 SRC | |
| 24 | 교환 | U8 Dev | u8 ndev |
이러한 각 호출 및 해당 매개 변수에 대한 자세한 내용은 아래 섹션에서 확인하십시오.
참고 : 일부 syscall은 구현되지 않을 수 있습니다. 예를 들어, 디렉토리가 지원되지 않는 컴퓨터에서 디렉토리 관련 SYSCALL을 생략 할 수 있습니다.
SYSCALL을 수행하려면 작업 번호가 레지스터 L 에 저장되어야합니다. 매개 변수는이 규칙에 따라 저장되어야합니다.
| API의 매개 변수 이름 | Z80 레지스터 |
|---|---|
| U8 Dev | H |
| u8 ndev | E |
| U8 플래그 | H |
| U8 CMD | C |
| U8 편지 | D |
| U8 코드 | H |
| U8 FS | E |
| U8 ID | H |
| U8 | A |
| U16 BUF | DE |
| U16 크기 | BC |
| U16 이름 | BC |
| U16 DST | DE |
| U16 Arg | DE |
| U16 경로 | DE |
| U16 Argv | DE |
| U16 기간 | DE |
| U16 시간 | DE |
| U16 날짜 | DE |
| U24 SRC | HBC |
| U32 오프셋 | BCDE |
마지막으로 코드는 RST $08 명령을 수행해야합니다 (재설정 벡터를 확인하십시오).
반환 된 값은 A에 배치됩니다. 해당 값의 의미는 각 호출마다 다루고 있습니다. 자세한 내용은 관련 루틴의 문서를 확인하십시오.
Kernel이 MMU 또는 No-MMU 모드로 컴파일되었는지 여부에 관계없이 열성 8 비트 OS 커널과의 사용자 프로그램 호환성을 최대화하려면 SyScalls 매개 변수 제약 조건이 동일합니다.
SyScall에 전달 된 모든 버퍼는 16KB 가상 페이지를 건너서는 안됩니다.
다시 말해, 크기 n 의 버퍼 buf 가상 페이지 i 에 위치한 경우 buf + n - 1 으로 가리키는 마지막 바이트는 정확히 동일한 i 에 위치해야합니다.
예를 들어, read SyScall이 호출되는 경우 :
DE = 0x4000 및 BC = 0x1000 , 매개 변수 0x4000 정확 0x7FFF DEDE = 0x4000 및 BC = 0x4000 , 매개 변수 0x4000 정확 0x7FFF DEDE = 0x7FFF 및 BC = 0x2 , de에 의해 지적 된 버퍼가 페이지 1과 Page2 사이에 있기 때문에 매개 변수는 올바르지 않습니다 .exec Zeal 8 비트 OS는 모노 작업 운영 체제이지만 여러 프로그램을 실행하고 유지할 수 있습니다. 프로그램 A가 프로그램 B를 실행하는 경우 exec SYSCALL 덕분에 EXEC_OVERRIDE_PROGRAM 또는 EXEC_PRESERVE_PROGRAM 될 수있는 mode 매개 변수를 제공해야합니다.
EXEC_OVERRIDE_PROGRAM :이 옵션은 커널에 프로그램 A를 더 이상 실행할 필요가 없다고 말하면 프로그램 B는 프로그램 A와 동일한 주소 공간에로드됩니다. 즉, 프로그램 B는 프로그램 A와 동일한 RAM 페이지 내에 프로그램 A와 함께로드되므로 덮어 씁니다.EXEC_PRESERVE_PROGRAM :이 옵션은 프로그램 B가 실행을 완료하고 exit Syscall을 호출 할 때까지 프로그램 A가 RAM에 보관해야한다고 커널에 알려줍니다. 이를 위해 커널은 새로로드 된 프로그램 B를 저장하는 3 개의 새로운 메모리 페이지 ( 16KB * 3 = 48KB )를 할당합니다. 일단 프로그램 B가 종료되면 커널은 프로그램 B에 이전에 할당 된 페이지를 해방시키고 프로그램 A의 메모리 페이지를 재발 명하며 필요한 경우, 필요한 경우, A CAN B의 종료 가치를 되 찾습니다. 실행 트리의 깊이는 menuconfig 에 옵션 CONFIG_KERNEL_MAX_NESTED_PROGRAMS 덕분에 정의됩니다. 한 번에 RAM으로 저장할 수있는 최대 프로그램 수를 나타냅니다. 예를 들어, 깊이가 3 인 경우 프로그램 A는 프로그램 B를 호출 할 수 있습니다. 프로그램 B는 프로그램 C를 호출 할 수 있지만 프로그램 C는 다른 프로그램을 호출 할 수 없습니다. 그러나 프로그램이 EXEC_OVERRIDE_PROGRAM 으로 exec 호출하면 새 프로그램이 현재 프로그램을 무시할 때 깊이가 증가 하지 않습니다 . 따라서 이전 예제를 되 찾으면 프로그램 C는 EXEC_OVERRIDE_PROGRAM 모드에서 exec Syscall을 호출하는 경우에만 프로그램을 호출 할 수 있습니다.
하위 프로그램을 실행할 때 전체 열린 장치 테이블 (파일, 디렉토리 및 드라이버 포함)을 실행하면 현재 디렉토리 및 CPU 레지스터가 공유 됩니다.
즉, 프로그램 A가 Descriptor 3이있는 파일을 열면 프로그램 B는이 색인을 상속하므로 해당 디스크립터를 읽거나 쓰기 또는 닫을 수도 있음을 의미합니다. 상호, B를 닫지 않고 파일, 디렉토리 또는 드라이버 및 종료를 엽니다면 프로그램 A도 액세스 할 수 있습니다. 따라서, 따라야 할 일반적인 지침은 종료하기 전에 프로그램이 항상 열린 설명자를 닫아야한다는 것입니다. 열린 장치 및 현재 디렉토리의 표가 재설정되는 유일한 순간은 초기 프로그램 (이전 예제의 프로그램 A)이 종료 될 때입니다. 이 경우 커널은 열린 장치 테이블의 모든 설명자를 닫고 표준 입력 및 출력을 다시 열고 초기 프로그램을 다시로드합니다.
이는 또한 어셈블리 프로그램에서 exec SyScall을 호출 할 때 성공시 HL을 제외한 모든 레지스터는 하위 프로그램에서 사용되므로 변경된 것으로 간주되어야 함을 의미합니다. 따라서 AF , BC , DE , IX 또는 IY 보존하려면 exec 호출하기 전에 스택을 밀어야합니다.
SYSCALLS는 모두 어셈블리와 C 모두에 제공된 헤더 파일에 문서화되어 있으므로 kernel_headers/ Directory 에서이 헤더 파일을 찾을 수 있습니다. 자세한 내용은 readme 파일을 확인하십시오.
드라이버는 다음을 포함하는 구조로 구성됩니다.
SER0 , SER1 , I2C0 등이 허용되지만 권장되지는 않습니다.init 루틴의 주소.read 변수 및 리턴 주소는 SyScall 테이블과 동일합니다.write 루틴의 주소.open 루틴의 주소.close 루틴 주소.seek 루틴의 주소.ioctl 루틴의 주소.deinit 루틴의 주소.간단한 운전자 등록의 예는 다음과 같습니다.
my_driver0_init:
; Register itself to the VFS
; Do something
xor a ; Success
ret
my_driver0_read:
; Do something
ret
my_driver0_write :
; Do something
ret
my_driver0_open :
; Do something
ret
my_driver0_close :
; Do something
ret
my_driver0_seek :
; Do something
ret
my_driver0_ioctl :
; Do something
ret
my_driver0_deinit :
; Do something
ret
SECTION DRV_VECTORS
DEFB "DRV0"
DEFW my_driver0_init
DEFW my_driver0_read
DEFW my_driver0_write
DEFW my_driver0_open
DEFW my_driver0_close
DEFW my_driver0_seek
DEFW my_driver0_ioctl
DEFW my_driver0_deinit 드라이버 등록은이 정보 (구조)를 DRV_VECTORS 라는 섹션 내에 넣는 것으로 구성됩니다. 순서는 모든 운전자 종속성이 컴파일 타임에 해결되므로 매우 중요합니다. 예를 들어, 드라이버 A 드라이버 B 에 의존하는 경우 DRV_VECTORS 섹션의 A 앞에 B 의 구조를 넣어야합니다.
부팅시 driver 구성 요소는 전체 DRV_VECTORS 섹션을 탐색하고 init Lourine을 호출하여 드라이버를 하나씩 초기화합니다. 이 루틴이 ERR_SUCCESS 반환하면 드라이버가 등록되고 사용자 프로그램이 열리고 읽기, 쓰기, IOCTL 등을 열 수 있습니다 ...
드라이버는 프로그램에 숨겨 질 수 있습니다. 이것은 커널 파일 시스템 계층에서만 액세스 해야하는 디스크 드라이버에게 편리합니다. 이를 위해서는 init 루틴이 ERR_DRIVER_HIDDEN 반환해야합니다.
응용 프로그램과 하드웨어 간의 통신은 위에서 설명한 SyScalls를 통해 모두 수행되므로 사용자 애플리케이션과 드라이버 또는 파일 시스템을 호출 해야하는지 여부를 결정하는 커널 사이의 계층이 필요합니다. 그러한 아키텍처의 계층 구조를 보여주기 전에 디스크와 드라이버에 대해 이야기합시다.
다른 층은 다음과 같이 볼 수 있습니다.
흐름도 TD;
앱 (사용자 프로그램)
VFS (가상 파일 시스템)
DSK (디스크 모듈)
DRV (드라이버 구현 : 비디오, 키보드, 직렬 등 ...)
FS (파일 시스템)
Sysdis (Syscall Dispatcher)
HW (하드웨어)
시간 (시간 및 날짜 모듈)
MEM (메모리 모듈)
로더 (로더 모듈)
앱 -syscall/rst 8-> sysdis;
sysdis-getDate/time-> time;
sysdis-마운트-> dsk;
sysdis-> vfs;
sysdis-맵-> mem;
sysdis- exec/exit-> 로더;
VFS-> DSK & DRV;
dsk <-> fs;
fs-> drv;
DRV-> HW;
열심 8 비트 OS는 한 번에 최대 26 개의 디스크를 지원합니다. 디스크는 A에서 Z 로의 문자로 표시됩니다. 시스템에서 디스크를 장착 할 위치를 결정하는 것은 디스크 드라이버의 책임입니다.
첫 번째 드라이브 A 는 시스템이 환경 설정 또는 구성을 찾는 것과 같이 특별합니다.
응용 프로그램에서 path 과 같습니다.
my_dir2/file1.txt/my_dir1/my_dir2/file1.txt my_dir2/file1.txtB:/your_dir1/your_dir2/file2.txt OS가 완전히 로마가 가능하고 파일 시스템이나 디스크가 부팅 할 필요는 없지만 기본적으로 init.bin 이라는 초기 프로그램을로드하려고하자마자 기본 디스크를 확인하고 해당 파일을 요청합니다. 따라서 가장 기본적인 스토리지조차도 파일 시스템 또는 유사한 것이 필요합니다.
이미 구현 된 첫 번째 "파일 시스템"을 "rawtable"이라고합니다. 이름이 표시된 바와 같이, 디렉토리가 아닌 파일의 연속을 스토리지 장치에서 특별한 순서로 나타내지 않습니다. 파일 이름 크기 제한은 옵션을 포함하여 16 자와 동일합니다 . 그리고 확장. 이를 C 코드와 비교하려면 각 파일을 정의하는 구조 배열이되고 파일의 내용이 동일한 순서로 이어집니다. Romdisk Packer 소스 코드는 packer/ 이 Repo의 루트에서 사용할 수 있습니다. 자세한 내용은 readme를 확인하십시오.
구현 된 두 번째 파일 시스템은 Zealfs입니다. 주요 목적은 8KB에서 64KB까지 매우 작은 저장에 포함되는 것입니다. 읽을 수 있고 쓰기 쉬우 며 파일과 디렉토리를 지원합니다. 전용 저장소에있는 자세한 정보.
열심 8 비트 OS에 좋은 세 번째 파일 시스템은 FAT16입니다. CompactFlash 및 SD 카드에서도 사용할 수있는 거의 모든 데스크탑 운영 체제에서 이미 지원되는 매우 유명한 이는 거의 필수입니다. 아직 구현되지 않았지만 계획되었습니다. FAT16은 작은 저장에 적합하지 않기 때문에 완벽하지는 않지만 Zealfs가 필요한 이유입니다.
열심 8 비트 OS는 커널과 대상 코드의 두 가지 주요 구성 요소를 기반으로합니다. 커널만으로는 아무것도하지 않습니다. 대상은 드라이버, 커널 내부에 사용되는 일부 MMU 매크로 및 링커 스크립트를 구현해야합니다. 링커 스크립트는 상당히 간단하며 z80asm Assembler의 최종 바이너리에 연결 해야하는 순서대로 섹션을 나열합니다.
커널은 현재 다음 섹션을 사용하며 모든 링커 스크립트에 포함되어야합니다.
RST_VECTORS : 재설정 벡터를 포함합니다SYSCALL_TABLE : syscall i 루틴 주소가 인덱스 i 에 저장되는 테이블이 포함되어 있습니다. 256에 정렬해야합니다.SYSCALL_ROUTINES : 재설정 벡터에서 호출되는 Syscall 디스패처가 포함되어 있습니다.KERNEL_TEXT : 커널 코드가 포함되어 있습니다KERNEL_STRLIB : 커널에 사용되는 문자열 관련 루틴이 포함되어 있습니다.KERNEL_DRV_VECTORS : 초기화 할 드라이버 배열을 나타냅니다. 자세한 내용은 드라이버 섹션을 확인하십시오.KERNEL_BSS : 커널 코드에서 사용하는 데이터가 포함되어 있어야 합니다 .DRIVER_BSS : 커널에서 직접 사용하지 않으므로 드라이버에서 정의되고 사용됩니다. 커널은 부팅시 0S로 설정되며 2 바이트보다 커야합니다. 앞서 말했듯이, 열성 8 비트 컴퓨터 지원은 여전히 부분적이지만 명령 줄 프로그램을 실행하기에 충분합니다. ROMDISK는 커널이 빌드되기 전에 생성되며 target/zeal8bit/unit.mk 에 지정된 script.sh 에서 수행됩니다.
이 스크립트는 init.bin 프로그램을 컴파일하고 컴파일 된 OS 바이너리에 연결될 Romdisk 안에 포함시킵니다. 최종 바이너리는 NOR 플래시로 직접 플래시 될 수 있습니다.
특별한 순서로 여전히 구현 해야하는 것 :
TRS-80 Model-I 컴퓨터에서 빠른 포트가 MMU가없는 대상으로 열심 8 비트 OS를 포트하고 구성하는 방법을 보여주기 위해 만들어졌습니다.
이 포트는 단순히 화면의 부트 배너를 표시하기 때문에 다소 간단합니다. 이를 위해 텍스트 모드의 비디오 드라이버 만 구현됩니다.
더 흥미로운 포트를 갖기 위해서는 다음과 같은 기능을 구현해야합니다.
init.bin /romdisk를 저장하는 디스크는 읽기 전용이므로 ROM에 저장할 수 있습니다.Shawn Sijnstra가 작성하고 유지 관리하는 EZ80 전원 Agon Light의 포트. Agon 특정 버그/요청에 해당 포크를 사용하십시오. 이는 비 MMU 커널을 사용하고 Zeal 8 비트 컴퓨터 구현이 지원하는 대부분의 기능을 구현합니다.
이 포트에는 바이너리가 올바른 위치에서 저장되고 실행되도록 로더가 필요합니다. 바이너리는 여기에서 사용할 수있는 Osbootz입니다.
포트는 터미널 모드를 사용하여 키보드 I/O를 단순화합니다. 이것은 또한 날짜 함수를 사용할 수 없음을 의미합니다.
다른 주목할만한 기능 :
Zeal 8 비트 OS MMU 버전을 다른 컴퓨터로 포트하려면 먼저 Z80의 64KB 주소 공간을 MMU 버전의 16KB 4 페이지로 나누는 메모리 매퍼가 있는지 확인하십시오.
포트 No-MMU Zeal 8 비트 OS를 위해 RAM을 가상 주소 0x4000 이상에서 사용할 수 있는지 확인하십시오. ROM을 갖는 가장 이상적인 사례는 OS의 첫 16KB 및 사용자 프로그램 및 커널 RAM의 나머지 48KB에서 RAM입니다.
대상이 호환되는 경우 지침을 따르십시오.
Kconfig 파일을 열고 config TARGET 및 config COMPILATION_TARGET 옵션에 항목을 추가하십시오. 이미 존재하는 것을 예로 들어보십시오.target/ 대상에 새 디렉토리를 작성하십시오. 이름은 새 config TARGET 옵션에 지정된 이름과 동일 해야 합니다.unit.mk 파일을 만듭니다. 조립할 모든 소스 파일 또는 포함 할 파일이 포함 된 파일입니다.unit.mk 파일을 채우십시오. 그렇게하려면 다음 변수를 make 수 있습니다.SRCS : 조립할 파일 목록. 일반적으로 이들은 드라이버 (필수)입니다.INCLUDES : 포함 할 수있는 헤더 파일이 포함 된 디렉토리PRECMD : 커널이 빌드를 시작하기 전에 실행되는 bash 명령POSTCMD : 커널이 빌드를 마친 후 실행되는 bash 명령mmu_h.asm 파일을 작성하여 커널에 포함될 MMU를 구성하고 사용합니다. 파일 target/zeal8bit/include/mmu_h.asm 확인하여 어떻게 생겼는지 확인하십시오.zos_disks_mount init.bin 함께 디스크를 마운트하는 드라이버가 하나 이상 있어야합니다.zos_vfs_set_stdout 와 함께 표준 아웃 (STDOUT)으로 등록하는 드라이버가 하나 이상 있어야합니다.완전한 ChangeLog의 경우 릴리스 페이지를 확인하십시오.
기부금을 환영합니다! 보거나 만나는 버그를 자유롭게 수정하거나 중요한 기능을 구현하십시오.
기여 :
(*) 좋은 커밋 메시지는 다음과 같습니다.
Module: add/fix/remove a from b
Explanation on what/how/why
예를 들어:
Disks: implement a get_default_disk routine
It is now possible to retrieve the default disk of the system.
Apache 2.0 라이센스에 따라 배포되었습니다. 자세한 내용은 LICENSE 파일을 참조하십시오.
개인 및 상업용 용도로 자유롭게 사용할 수 있습니다. 각 파일에있는 보일러 플레이트를 제거해서는 안됩니다.
제안이나 요청을 보려면 [at] Zeal8bit [dot] com에서 저에게 연락 할 수 있습니다.
기능 요청의 경우 문제 또는 풀 요청을 열 수도 있습니다.
그럼에도 불구하고 그들은 비 휘발성으로 간주되어서는 안됩니다 . 다시 말해, 인터럽트 핸들러는 대체 레지스터 내에 작성된 데이터가 다음에 호출 될 때까지 보관 될 것이라고 가정하지 않아야합니다. ↩