U E D R , A S I H C RSS

VM Ware/OS Implementation Test

2. ž‘„•œ ดœ 

OS๋ฅผ ๋งŒ๋“ค–ด๋ณด๊ณ  ‹ถ€ ๋งˆŒ— ๋ฌดž‘ • ๋›–ด ๋“ค—ˆ๋Š”๋ฐ ๋Œ€๋ถ€๋ถ„ ™˜๊ฒฝ€ ๋ฆฌ๋ˆ…Šคƒด
gcc˜€Šต๋‹ˆ๋‹ค. •˜ง€๋งŒ  €๋Š” windows ™˜๊ฒฝ•˜˜ vc ๊ฐœ๋ฐœ„ ฃผ๋กœ •ด™”œผ๋ฏ€๋กœ ๋ฌดฒ™
๋ถˆŽธ(?)–ˆŠต๋‹ˆ๋‹ค. Djgpp ๋ผ๋Š” dosšฉ gcc ฌŒ… ๋ฒ„ „๊ณผ œˆ๋„šฐšฉ cygwin Œจ‚คง€๋ฅผ
‚ฌšฉ•˜๋ฉด —ญ‹œ ๋™ผ•˜๊ฒŒ gcc๋ฅผ œˆ๋„šฐ—„œ ปดŒŒผ •  ˆ˜ žˆŠต๋‹ˆ๋‹ค ๊ทธ๋ž˜๋„  €๋Š” vc˜
—๋””Œ… ™˜๊ฒฝด ๋ง˜— ๋“ค–ด„œ ๋””๋ฒ„๊น…๊นŒง€๋Š” ž˜๋“ค๊ฒ ง€๋งŒ (–ดฐจ”ผ ปค๋„ ๋””๋ฒ„๊น…•˜๋ ค๋ฉด
ŠคŠค๋กœ ž‹ ˜ ปค๋„ ๋””๋ฒ„ฐ๋ฅผ ๋งŒ๋“ค–ด•ผ •˜๋Š” ๊ฐ ๊ฐ™Šต๋‹ˆ๋‹ค. ) —๋””Œ…๊ณผ ปดŒŒผ
๊ทธ๋ฆฌ๊ณ  ๋งปค๋ฅผ vc6๋ฅผ ‚ฌšฉ•˜๊ณ  ‹ถ—ˆ๊ณ  ๊ทธ๋ž˜„œ ด๋ฅผ ‚ฌšฉ•  ˆ˜ žˆ๋Š” ๋ฐฉ๋ฒ•„ †Œ๊ฐœ•˜๋ ค
•ฉ๋‹ˆ๋‹ค.

3. ฐธ๊ณ •˜๋ฉด ข‹€ ‚ฌดŠธ๋“ค

–ด๋ คšด ˜๋ฌธ OS๊ฐœ๋ฐœ๋ฐฉ๋ฒ•„ •œ๊ธ€™” •ดฃผ๋Š” ๊ณ ๋งˆšด ‚ฌดŠธ
Chobits os˜ †ŒŠค๋ฅผ –ป„ ˆ˜ žˆŠต๋‹ˆ๋‹ค.
๋ฌดฒ™ ข‹€ Protected mode— ๋Œ€•œ „ค๋ช…๊ณผ †ŒŠค๋ฅผ ๋‹ด๊ณ  žˆ๋Š” ‚ฌดŠธ
http://www.nondot.org/sabre/os/articles
-
OS— ๋Œ€•œ  „๋ฐ˜ ธ ž๋ฃŒ๊ฐ€ žˆŠต๋‹ˆ๋‹ค.
http://www.osdever.net/
-
Bona Fide OS ๊ฐœ๋ฐœ Šœ† ๋ฆฌ–ผ ‚ฌดŠธ
http://mega-tokyo.com/osfaq2/
-
OS FAQ
http://www.osdev.org/
-
†ŒŠค๊ฐ€ ๊ณต๊ฐœ๋œ —ฌ๋Ÿฌ os๊ฐ€ žˆŠต๋‹ˆ๋‹ค.
http://www.bellona2.com
-
˜ผž„œ GUI OS๋ฅผ ๋งŒ๋“œ‹œ๊ณ  …๋„ ถœŒ•˜‹  ๋ถ„˜ ‚ฌดŠธ
http://ksyspro.org
-
•œ๊ตญ ž„๋ฒ ๋””๋“œ ๊ฐœ๋ฐœž ๋ชจž„

4. Protected i386 OS๋ฅผ œ„•œ 잛€ „ค๋ช…

Intel€ ๋‹ค๋ฅธ cpu ๋ฒค๋”๋ณด๋‹ค —ญ‚ฌ๊ฐ€ ˜ค๋ž˜๋˜–ด„œ 4bit microprocessorธ 4004—„œ
ถœ๋ฐœ•ด„œ 8bit cpu 8008, 8080, 16๋น„Šธ 8086, 80186, 80286, 32๋น„Šธ 80386, 80486,
80586 (๋˜๋Š” P5 ๊ทธ๋Ÿฌ๋‚˜ ˆž๋Š”  €ž‘๊ถŒ ๋ณด˜ธ๋ฅผ ๋ฐ›ง€ ๋ชป•œ๋‹ค๊ธธ๋ž˜ ด›„— Pentiumœผ๋กœ
๋ฐ”๋€Œ—ˆŠต๋‹ˆ๋‹ค ). ด๋ ‡๊ฒŒ ๊ธด —ญ‚ฌ๋ฅผ ๊ฐ–๊ณ  žˆ๋Š” ๋ณดŽธ ธ cpu 8080 ๋˜๋Š” 8086 †ต‹€–ด
intel x86 cpu—„œ ๋Œ๋˜ ”„๋กœ๊ทธ๋žจ๋„ 586—„œ๋„ ˆ˜–‰๋˜๋„๋ก •˜œ„˜ธ™˜„ ๊ฐ–๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

ด •˜œ„˜ธ™˜ ๋•Œ๋ฌธ— •„๋ฌด๋ฆฌ ตœ‹  ปด“จ„ฐ๋„ ฒ˜Œ ๋ถ€Œ…‹œ—๋Š” ๋น ๋ฅธ x86 ฒ˜๋Ÿผ
ˆ˜–‰๋˜๋„๋ก „ค๊ณ„๋˜—ˆŠต๋‹ˆ๋‹ค. ๋ถ€Šธ„„—„œ ด ๋น ๋ฅธ x86—„œ ตœ‹ ˜ ๊ธฐ๋Šฅ„ ‚ฌšฉ•˜๋Š”
i386+ ™˜๊ฒฝœผ๋กœ ๋งŒ๋“ค๊ธฐ œ„•ด„œ  –ด๋„ ๋‹คŒ๊ณผ ๊ฐ™€ ผ„ •˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

ORG 0x7C00 - PC๊ฐ€ ๋ฆฌ…‹๋˜๋ฉด ๋ถ€Œ…๋  ๋””๋ฐ”ดŠค˜ ฒซ๋ฒˆงธ „„ฐ(512๋ฐ”ดŠธ)๋ฅผ
ฝ–ด ๋ฉ”๋ชจ๋ฆฌ 0x7C00— ˜ฌ๋ ค ๋†“€ ›„ ด ฝ”๋“œ๋กœ  ”„•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ„œ ๋ถ€Šธ„„
ฝ”๋“œ๋Š” ๊ทธ ๋ฉ”๋ชจ๋ฆฌ—„œ ‹œž‘•œ๋‹ค๊ณ  ง€ ••ด•ผ • ๊ฒƒž…๋‹ˆ๋‹ค.

A20 enable - ˜ˆ „—๋Š” ‹ค œ ๋ฉ”๋ชจ๋ฆฌฌ๊ธฐ๊ฐ€ ฌง€ •Š•„ 1M ด•˜๋งŒ  ‘๊ทผ•˜๋„๋ก
„ค๊ณ„๋˜—ˆ๋Š”๋ฐ ด   ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ 1Mดƒ ๋˜๋Š” ๊ฒƒด ๋งŽ•„ 1M ดƒ„ ‹ค œ  ‘๊ทผ •˜๊ธฐ œ„•ด„œ
•ดฃผ–ด•ผ •ฉ๋‹ˆ๋‹ค.

Protected mode - ฒ˜Œ ๋ถ€Œ…• ๋• x86 Real Mode๋ผ๋Š” „ธ๊ทธ๋จผŠธ:˜ค”„…‹
ง€ • ๋ฐฉ‹œผ๋กœ ˆ˜–‰๋˜ง€๋งŒ 80286ดƒ—„œ๋Š” ๋ณด˜ธ๋ชจ๋“œ๊ฐ€ ง€›๋˜—ˆ๊ณ  (ตœ๋Œ€16M๊ฐ€๋Šฅ)
80386—„œ๋Š” 4G๊นŒง€  ‘๊ทผ ๊ฐ€๋Šฅ•˜๋„๋ก ๋˜—ˆŠต๋‹ˆ๋‹ค.

ปค๋„๋กœ๋“œ - ๋ถ€Šธ„„ฝ”๋“œ๋Š” C๋กœ๋œ ๋ฐ”ด๋„ˆ๋ฆฌ ปค๋„„ —ฌ๋Ÿฌ „„—„œ
ฝ–ด„œ Šน • ๋ฉ”๋ชจ๋ฆฌ ๋ฒˆง€— ๋กœ๋“œ•œ ›„ ๊ทธ ‹œž‘ •จˆ˜ (—”Šธ๋ฆฌ ฌธŠธ •จˆ˜)๋กœ  ”„•˜๊ฒŒ
๋ฉ๋‹ˆ๋‹ค.

5. ค€๋น„๋ฌผ


VC6,
- ปค๋„˜ ปดŒŒผ ๋ฐ ๋ง‚น„ ๋‹ด๋‹น•ฉ๋‹ˆ๋‹ค.
- šฐ๋ฆฌ๋Š” ๋””Šคผ“๋„ ‚ฌšฉ•˜ง€ •Š๊ณ  ๋ฐ”๋กœ ปดŒŒผ•ด„œ ด๋ฏธง€๋กœ ๋œฌ ›„ VMWare๋กœ
๋กœ๋“œ•  ๊ฒƒž…๋‹ˆ๋‹ค. ( no ”Œ๋กœ”ผ ๋ถ€Œ…๋””Šคผ“, no ๋ฆฌ๋ถ“, no test machine )

Nasm
- Netwide Asmœผ๋กœ at&t ๊ณ„—ด ๋ฐ intel ๊ณ„—ด ๋‘˜๋‹ค ง€›•˜๊ณ  target format๋„
๋งŽด ง€›•˜๋Š” –ด…ˆ๋ธ”๋Ÿฌž…๋‹ˆ๋‹ค. „น˜๊ณผ •—†ด ๊ทธ๋ƒฅ nasm.exe ๋งŒ žˆœผ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

6. †ŒŠค ŒŒผ๋“ค

bootsect.asm
- ๊ฐ„๋‹จ•œ ๋ณด˜ธ๋ชจ๋“œ(„ธ๊ทธ๋จผ…Œด…˜๋ฐฉ‹) „ž… ๋ฐ ปค๋„ ๋กœ๋“œ ๋ถ€Šธ๋กœ๋”

main.c
- VC๋กœ ปดŒŒผ๋  ž‘€ ปค๋„

Makeboot.exe
- ๋ถ€Šธ„„™€ ปค๋„ด๋ฏธง€๋ฅผ merge•˜๋Š” ๊ฐ„๋‹จ•œ makeboot.c ปดŒŒผ•ด„œ ž‹ ๋งŒ˜
๋ถ€Šธ ด๋ฏธง€ ๋œจ๋Š” ”„๋กœ๊ทธ๋žจ ๋งŒ๋“ค๋ฉด๋œ๋‹ค.

7. †ŒŠค

7.1. bootsect.asm

[BITS 16]       ; We need 16-bit intructions for Real 
mode

[ORG 0x7C00]    ; The BIOS loads the boot sector into memory location 
0x7C00

reset_drive:

        mov ah, 0               ; RESET-command

        int 13h                 ; Call interrupt 13h

        or ah, ah               ; Check for error code

        jnz reset_drive         ; Try again if ah != 0

        ;vc—„œ /base 10000 ๋กœ 헀๊ธฐ ๋•Œ๋ฌธ— —ฌ๊ธฐ„œ๋ถ€„ฐ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋กœ๋“œ
        ; •ด•ผ •œ๋‹ค. ES:BX ๋กœ 1000:0000h ด๊ธฐ ๋•Œ๋ฌธ— •„๋ž˜ฒ˜๋Ÿผ •œ๋‹ค.

        mov ax, 1000h           ; es:bx <-- 1000:0000h 

        mov es, ax
        mov bx, 0h          ; Destination address = 0000:1000

        mov ah, 02h             ; READ SECTOR-command

        ; ๋‘๋ฒˆงธ „„ฐ๋ถ€„ฐ 3นธ„„ฐ๊ฐ€ ปค๋„ด๋ฏธง€ „„ฐ๋‹ค.

        mov al, 3h             ; Number of sectors to read = 1

        mov ch, 0               ; Cylinder = 0

        ; ˜„žฌ ฒซ๋ฒˆงธ„„ฐ512 ด๋ฉฐ ๋‘๋ฒˆงธ „„ฐ๋ถ€„ฐ 3๊ฐœ „„ฐ๊ฐ€ ปค๋„ด๋ฏธง€๋‹ค

        mov cl, 02h             ; Sector = 2

        mov dh, 0               ; Head = 0

        int 13h                 ; Call interrupt 13h

        or ah, ah               ; Check for error code

        jnz reset_drive         ; Try again if ah != 0

A20Address:    ; Set A20 Address line here

    CLI

    CALL enableA20

    STI
    JMP Continue

enableA20:
        call enableA20o1

        jnz short enableA20done

        mov al,0d1h

        out 64h,al

        call enableA20o1

        jnz short enableA20done

        mov al,0dfh

        out 60h,al

enableA20o1:

        mov ecx,20000h

enableA20o1l:

        jmp short $+2

        in al,64h

        test al,2

        loopnz enableA20o1l

enableA20done:

        ret

Continue:   

        cli                 ; Disable interrupts, we want to be alone

        xor ax, ax

        mov ds, ax              ; Set DS-register to 0 - used by lgdt

        lgdt [gdt_desc]         ; Load the GDT descriptor

        mov eax, cr0            ; Copy the contents of CR0 into EAX

        or eax, 1               ; Set bit 0

        mov cr0, eax            ; Copy the contents of EAX into CR0

        jmp 08h:clear_pipe      ; Jump to code segment, offset clear_pipe

[BITS 32]                       ; We now need 32-bit instructions

clear_pipe:

        mov ax, 10h             ; Save data segment identifyer

        mov ds, ax              ; Move a valid data segment into the data segment register

        mov ss, ax              ; Move a valid data segment into the stack segment register

        mov esp, 090000h        ; Move the stack pointer to 090000h

        ; 10200h๋กœ  ”„ 200h๋Š” vc๋กœ ๋ง‚น•˜๋ฉด ๊ธฐ๋ณธ PE—ค๋”(200h)๋ฅผ ๋ถ™—ฌ„œ ๋”–ˆ๋‹ค.

        ; 10200h ฆ‰ 1000:0200h ๋กœ  ”„

        ;jmp 1000:0200h

        jmp 10200h

        

gdt:                    ; Address for the GDT

gdt_null:               ; Null Segment

        dd 0

        dd 0

gdt_code:               ; Code segment, read/execute, nonconforming

        dw 0FFFFh

        dw 0

        db 0

        db 10011010b

        db 11001111b

        db 0

gdt_data:              ; Data segment, read/write, expand down

        dw 0FFFFh

        dw 0

        db 0

        db 10010010b

        db 11001111b

        db 0

gdt_end:		; Used to calculate the size of the GDT

gdt_desc:               ; The GDT descriptor

        dw gdt_end - gdt - 1    ; Limit (size)

        dd gdt                  ; Address of the GDT

times 510-($-$$) db 0           ; Fill up the file with zeros

        dw 0AA55h                ; Boot sector identifyer
•„๋ž˜ฒ˜๋Ÿผ –ด…ˆ๋ธ” •˜—ฌ ˜ค๋ธŒ  ๋ถ€Šธ๋กœ๋” ๋ฐ”ด๋„ˆ๋ฆฌ๋ฅผ –ป–ด๋‚ด•ผ
•ฉ๋‹ˆ๋‹ค.

nasm -f bin bootsect.asm -o bootsect.bin

๋‹คŒ€ ๋ถ€Šธ๋กœ๋”™€ ปค๋„ ด๋ฏธง€๋ฅผ •ฉณ„œ •˜๋‚˜˜ ๋ถ€Œ…ด๋ฏธง€๋กœ ๋งŒ๋“ค–ดฃผ๋Š” makeboot.c
ž…๋‹ˆ๋‹ค. ๋”ฐ๋กœ ”„๋กœ Šธ๋ฅผ ๋งŒ๋“ค–ด„œ ๊ฐ„๋‹จžˆ ปดŒŒผ•ด„œ makeboot.exe๋ฅผ ๋งŒ๋“ค๋„๋ก
•ฉ๋‹ˆ๋‹ค.
#include 

int 
main(int argnr, char *args[])

{

  FILE 
*output, *input;

  int 
i, bytes_read, sectors_read, bytes_from_file;

  char 
buffer[512];

  if 
(argnr < 4) {

    printf("Invalid 
number of parameters.\n\n");

    printf("USAGE: 
%s [output] [input 1] [input 2] ... [input n]\n", args[0]);

    printf("Example: 
%s a.img bootsect.bin kernel.bin");

    exit(0);

  }

  output 
= fopen(args[1], "r");

// 
๋ฎ–ด “ฐ๊ธฐ • ๊บผ๋ƒ๊ณ  ๋ฌผ–ด๋ณด๋Š” ฝ”๋“ ๋ฐ ๊ทธ๋ƒฅ ๋ฎ–ด“ฐž. --

  if 
(output != NULL) {

    buffer[0] 
= 0;

  }

  fclose(output);

  output 
= fopen(args[1], "wb");

  for 
(i = 2; i < argnr; i++) {

    input 
= fopen(args[i], "rb");

    if 
(input == NULL) {

      printf("Missing 
input file %s. Aborting operation...", args[i]);

      fclose(output);

      exit(1);

    }

    bytes_read 
= 512;

    bytes_from_file 
= 0;

    sectors_read 
= 0;

    while(bytes_read 
== 512 && !feof(input)) {

      bytes_read 
= fread(buffer, 1, 512, input);

      if 
(bytes_read == 0)

        break;

      if 
(bytes_read != 512)

        memset(buffer+bytes_read, 
0, 512-bytes_read);

      sectors_read++;

      fwrite(buffer, 
1, 512, output);

      bytes_from_file 
+= bytes_read;

    }

    printf("%d 
sectors, %d bytes read from file %s...\n", sectors_read, bytes_from_file, 

args[i]);

    fclose(input);

  }

  fclose(output);

  return 
0;

}

๋‹คŒ€ ปค๋„ †ŒŠคž…๋‹ˆ๋‹ค.


// 
bro (bro@shinbiro.com)2004-02-17 - initial ( vc dev envronment setting )

// 
starting function

void 
start()

{   

    char* 
hello = "Hello OS!";

    unsigned 
char* vidmem = (unsigned char*)0xB8000;

    while( 
*hello != '\0' )        

    {

        *vidmem++ 
= *hello++;

        *vidmem++ 
= 7;        // ๋ฌธž ๊ธฐ๋ณธ †„

    }   

    

    // 
ปค๋„ด ๋๋‚˜๋ฉด •ˆ๋œ๋‹ค. ๊ณ„† ๋Œ•„•ผ•œ๋‹ค.   

    for(;;);

}

7.2. Visual C++ ปดŒŒผ ™˜๊ฒฝ ๊ตฌ„•˜๊ธฐ


œ„˜ ปค๋„ †ŒŠค๋ฅผ ปดŒŒผ •˜๊ธฐ œ„•ด„œ VC ปดŒŒผ ™˜๊ฒฝ„ ๊ตฌ„•ด๋ณด๋„๋ก •ฉ๋‹ˆ๋‹ค.

๋จผ € Win32 Console Applicationœผ๋กœ ๊ฐ„๋‹จžˆ ”„๋กœ Šธ๋ฅผ ƒ„•ฉ๋‹ˆ๋‹ค.

๋””๋ฒ„๊น…€ ๋ชป•˜๋‹ˆ ๊ทธ๋ƒฅ Release ๋ชจ๋“œ๋กœ „ ƒ•œ ›„ C++ „Œ…„ •„๋ž˜ฒ˜๋Ÿผ •ฉ๋‹ˆ๋‹ค.
/nologo /G4 /Zp1 /ML /W3 /vmg /vd0 /GX /Od /Gf /FAc /Fa"Release/" /Fo"Release/" /Fd"Release/" /FD /c
Linkƒญ˜ ˜ต…˜€ •„๋ž˜ฒ˜๋Ÿผ •ฉ๋‹ˆ๋‹ค.
/nologo /base:"0x10000" /entry:"start" /subsystem:console /incremental:no /pdb:"Release/testos.pdb" /map:"Release/testos.map" /machine:I386 /nodefaultlib /out:"testos.bin" /DRIVER /align:512 /FIXED
๋˜•œ ปดŒŒผ ž‘—…—„œ ๋ฐ”๋กœ ๋ถ€Šธ„„ฐ๋„ ปดŒŒผ•˜๊ณ  ปดŒŒผ ๋๋‚˜๋ฉด ๋ฐ”๋กœ ๋ถ€Šธ ด๋ฏธง€๋„
๋งŒ๋“ค๋„๋ก Pre-Link™€ Post-Build๋ฅผ ž‘„•ฉ๋‹ˆ๋‹ค.

ปดŒŒผ„ •ด๋ด…๋‹ˆ๋‹ค.
Deleting intermediate files and output files for project 'testos - Win32 Release'.
--------------------Configuration: testos - Win32 Release--------------------
Compiling...
main.c
Linking...
LINK 
: warning LNK4096: /BASE value "10000" is invalid for Windows 95; image may 
not run 1 sectors, 512 bytes read from file bootsect.bin...
3 sectors, 1536 bytes read from file testos.bin...
testos.bin 
- 0 error(s), 1 warning(s)

8. VMWare …ŒŠคŠธ ™˜๊ฒฝ ๊ตฌ„•˜๊ธฐ

ปดŒŒผ„ ๋งˆน˜๊ณ  ๋‚˜๋ฉด •„๋ž˜™€ ๊ฐ™€ ƒƒ‰๊ธฐ ๋ชจŠตด ๋  ๊ฒƒž…๋‹ˆ๋‹ค. ๋งˆง€๋ง‰œผ๋กœ …„๋œ testos.img ๊ฐ€ šฐ๋ฆฌ˜ ปค๋„ ด๋ฏธง€๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.
zeropage:VMWareOSImplementationTest01.gif
Partcopy.exe ˆ„ ‚ฌšฉ•˜—ฌ ๋ถ€Œ… ๋””Šคผ“— ๋†“„ ˆ˜๋„ žˆง€๋งŒ ๋ฒˆฐ๋กญŠต๋‹ˆ๋‹ค. ๋”ฐ๋ผ„œ VMWare—„œ ง ‘ ด๋ฅผ ๋””Šคผ“ ด๋ฏธง€๋กœ ๋กœ๋“œ•˜๋„๋ก •ฉ๋‹ˆ๋‹ค.
zeropage:VMWareOSImplementationTest02.gif
๋ฌดกฐ๊ด ๊ทธ๋ƒฅ ๊ธฐ๋ณธœผ๋กœ Next •ฉ๋‹ˆ๋‹ค.
zeropage:VMWareOSImplementationTest03.gif
 œผ ค‘š”•œ ๊ฒƒ€ ด๋ ‡๊ฒŒ ๋งŒ๋“  ๊ฐ€ƒ testos ˜ ”Œ๋กœ”ผ ๋””Šคผ“ ๋ถ€Œ… „ •ž…๋‹ˆ๋‹ค.
zeropage:VMWareOSImplementationTest04.gif
Use Floppy Image— •ด๋‹น img ŒจŠค ๋งžถ”๋„๋ก •ฉ๋‹ˆ๋‹ค.

ด œ ‹ค–‰•ด๋ด…๋‹ˆ๋‹ค.
zeropage:VMWareOSImplementationTest05.gif
Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2021-02-07 05:28:21
Processing time 0.0264 sec