diff options
-rw-r--r-- | Makefile | 32 | ||||
-rw-r--r-- | basic.s | 24 | ||||
-rw-r--r-- | bootsect.s | 54 | ||||
-rw-r--r-- | kernel.s | 290 | ||||
-rw-r--r-- | reader.c | 49 | ||||
-rw-r--r-- | yotlibc/Makefile | 18 | ||||
-rw-r--r-- | yotlibc/bccfunc.s | 9 | ||||
-rw-r--r-- | yotlibc/char_in.s | 12 | ||||
-rw-r--r-- | yotlibc/char_vga.s | 141 | ||||
-rw-r--r-- | yotlibc/char_vhl.c | 149 | ||||
-rw-r--r-- | yotlibc/str_in.c | 279 | ||||
-rw-r--r-- | yotlibc/str_out.s | 98 | ||||
-rw-r--r-- | yotlibc/yotlibc.h | 153 | ||||
-rw-r--r-- | yotlibc/yotlibc.txt | 140 |
14 files changed, 1448 insertions, 0 deletions
diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..e81343c --- /dev/null +++ b/Makefile @@ -0,0 +1,32 @@ + +.PHONY: all clean run + +all: floppy.img + +floppy.img: 55aa bootsect kernel reader + dd if=/dev/zero of=$@ bs=512 count=2880 + dd if=55aa of=$@ bs=1 count=2 seek=510 conv=notrunc + dd if=bootsect of=$@ conv=notrunc + dd if=kernel of=$@ bs=512 seek=1 conv=notrunc + dd if=reader of=$@ bs=512 seek=9 conv=notrunc + +bootsect: bootsect.s basic.s + nasm -f bin $< -o $@ +kernel: kernel.o + ld86 -T 0x0000 -d kernel.o -o kernel +reader: reader.o yotlibc/yotlibc.a + ld86 -T 0x0000 -d reader.o yotlibc/yotlibc.a -o reader + +kernel.o: kernel.s + nasm -f as86 $< -o $@ +reader.o: reader.c + bcc -ansi -Mc -Iyotlibc -c $< -o $@ + +55aa: + echo "0000000: 55aa" | xxd -r > $@ + +run: floppy.img + qemu-kvm -fda floppy.img $(QARG) + +clean: + rm -f bootsect kernel kernel.o 55aa reader reader.o floppy.img @@ -0,0 +1,24 @@ +putcharhex: ; bl=argument
+ pusha
+ mov ah, 0x0e
+ mov al, bl
+ and al, 0xf0
+ shr al, 4
+ call fourbit2hex
+ int 0x10
+ mov al, bl
+ and al, 0x0f
+ call fourbit2hex
+ int 0x10
+ popa
+ ret
+fourbit2hex: ; al=argument=result
+ cmp al, 10
+ jae fourbit2hex_alpha
+ add al, '0'
+ ret
+fourbit2hex_alpha:
+ add al, 'A'
+ sub al, 10
+ ret
+
diff --git a/bootsect.s b/bootsect.s new file mode 100644 index 0000000..5e24681 --- /dev/null +++ b/bootsect.s @@ -0,0 +1,54 @@ + org 0x7c00 ; boot sector
+
+entry:
+ ; now loading from disk
+ mov cx, 3 ; retry count
+ mov ax, 0x0000
+ mov ds, ax
+ mov ax, 0x9050
+ mov es, ax ; set es, the destination
+ mov bx, 0
+loaddisk:
+ mov si, cx
+ mov ah, 0x02 ; function: read disk sectors
+ mov al, 8 ; sector count
+ mov dh, 0 ; head
+ mov dl, 0 ; drive number
+ mov ch, 0 ; track
+ mov cl, 2 ; sector offset
+ int 0x13
+ jnc loadok
+ mov bl, al
+ call putcharhex
+ mov cx, si
+ loop loaddisk
+
+ ; load failed
+ mov ah, 0x0e
+ mov al, 'X'
+ int 0x10
+ jmp $
+
+ ; load OK
+loadok:
+ mov ah, 0x0e
+ mov al, 'P'
+ int 0x10
+ mov al, 'R'
+ int 0x10
+ mov al, 'E'
+ int 0x10
+ mov al, 'Y'
+ int 0x10
+ mov al, 'O'
+ int 0x10
+ mov al, 'T'
+ int 0x10
+ mov ax, 0x9050
+ mov ds, ax
+ mov es, ax
+ mov ss, ax
+ db 0xEA
+ dd 0x90500000
+
+%include "basic.s"
diff --git a/kernel.s b/kernel.s new file mode 100644 index 0000000..da018d1 --- /dev/null +++ b/kernel.s @@ -0,0 +1,290 @@ + global _main
+
+_main:
+ mov sp, 0x3ffe
+;--------------------------------------------------
+set_environment:
+ xor ax, ax
+ push es
+ mov es, ax
+ db 0xE8
+ add al, [bx+si]
+ db 0xEB
+ db 0x05
+ pop ax
+ sub sp, 2
+ ret
+;--------------------------------------------------
+do_memory_control:
+ add ax, 0x17
+ cli
+ mov [es:0x140], ax
+ mov [es:0x142], cs
+ sti
+ jmp do_memory_control_end
+ mov ax, 0x5301
+ xor bx, bx
+ int 0x15
+ mov ax, 0x530E
+ xor bx, bx
+ mov cx, 0x0102
+ int 0x15
+ mov ax, 0x5307
+ mov bx, 0x0001
+ mov cx, 0x0003
+ int 0x15
+ iret
+do_memory_control_end:
+ pop es
+;--------------------------------------------------
+set_keyboard:
+ xor ax, ax
+ push es
+ mov es, ax
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ db 0xE8
+ add al, [bx+si]
+ db 0xEB
+ db 0x05
+ pop ax
+ sub sp, 2
+ ret
+ add ax, 0x2C
+ cli
+ mov si, [es:0x24]
+ mov di, [es:0x26]
+ mov [es:0x324], si
+ mov [es:0x326], di
+ mov [es:0x24], ax
+ mov [es:0x26], cs
+ sti
+ jmp near set_keyboard_end
+
+code_for_scancode:
+ push ax
+ push bx
+ push es
+ mov ax, 0x40
+ mov es, ax
+
+ mov bx, 0x0007
+ mov ah, 0x0E
+ mov al, '['
+ int 0x10
+
+ mov bx, 0x0007
+ mov ah, 0x0E
+ mov ax, [es:0x1A]
+ call putint
+
+ mov bx, 0x0007
+ mov ah, 0x0E
+ mov al, ','
+ int 0x10
+
+ mov ax, [es:0x1C]
+ mov dx, ax
+ call putint
+
+
+ mov bx, 0x0007
+ mov ah, 0x0E
+ mov al, ']'
+ int 0x10
+
+ pop es
+ pop bx
+ pop ax
+ int 0xC9
+ iret
+set_keyboard_end:
+ pop es
+;--------------------------------------------------
+load_bin_from_floppy:
+ xor ax, ax
+ mov ax, 0x0050
+ mov es, ax
+ mov bx, 0x0000
+ ; start loading
+ mov si, cx
+ mov ah, 0x02 ; function: read disk sectors
+ mov al, 8 ; sector count
+ mov dh, 0 ; head
+ mov dl, 0 ; drive number
+ mov ch, 0 ; track
+ mov cl, 10 ; sector offset
+ int 0x13
+ jc load_bin_failed
+;--------------------------------------------------
+view_loader_message:
+ mov ah, 0x0e
+ mov al, ':'
+ mov bx, 0x0007
+ int 0x10
+ mov al, 0x0d
+ int 0x10
+ mov al, 0x0a
+ int 0x10
+;--------------------------------------------------
+fake_loader:
+ db 0xE8
+ add al, [bx+si]
+ db 0xEB
+ db 0x05
+ db 0x58
+;--------------------------------------------------
+virtual_device:
+ db 0x83
+ in al, dx
+ db 0x02
+ ret
+;--------------------------------------------------
+real_loader:
+ jmp near very_very_far_func
+ jmp program_exit
+;--------------------------------------------------
+load_bin_failed:
+ mov dx, 0
+ mov ds, dx
+ mov es, dx
+ xor ah, al
+ call putint
+ jmp _main
+;--------------------------------------------------
+program_exit:
+ mov bx, cs
+ mov ds, bx
+ mov es, bx
+ mov ss, bx
+ mov si, 0x3FFE
+ mov sp, [si]
+ mov dx, ax
+; pop dx
+; call char_vga_setbios
+
+ mov bx, 0x0007
+ mov ah, 0x0E
+ mov al, 0x0D
+ int 0x10
+ mov al, 0x0A
+ int 0x10
+
+ mov bx, 0x0007
+ mov ah, 0x0E
+ mov al, 'E'
+ int 0x10
+ mov al, 'x'
+ int 0x10
+ mov al, 'i'
+ int 0x10
+ mov al, 't'
+ int 0x10
+ mov al, ' '
+ int 0x10
+ mov al, 'C'
+ int 0x10
+ mov al, 'o'
+ int 0x10
+ mov al, 'd'
+ int 0x10
+ mov al, 'e'
+ int 0x10
+ mov al, ':'
+ int 0x10
+ mov al, ' '
+ int 0x10
+
+ mov ax, dx
+ call putint
+
+; mov ax, dx
+; call putint
+
+; mov ax, dx
+; call putint
+
+ int 0x10
+ db 0xEB, 0xFE
+ jmp _main
+;--------------------------------------------------
+putint: ; ax=argument
+ pusha
+ mov di, 0 ; dest index
+ mov si, 10 ; divisor, ax=dividend
+
+ putint_divloop:
+ mov dx, 0 ; clear upper bits
+ div si
+ add dx, '0'
+ mov byte [putintbuf+di], dl
+ inc di
+ cmp ax, 0
+ ja putint_divloop
+
+ mov ah, 0x0e
+ mov bx, 0x0007
+
+ putint_print:
+ dec di
+ mov al, byte [putintbuf+di]
+ int 0x10
+ cmp di, 0
+ ja putint_print
+
+ popa
+ ret
+;--------------------------------------------------
+very_very_far_func:
+; call char_vga_savebios
+; push dx
+ mov si, 0x3FFE
+ mov [si], sp
+
+ mov bx, 0x0050
+ mov ds, bx
+ mov es, bx
+ mov ss, bx
+ mov bx, 0xFFFF
+ mov si, bx
+ mov dx, 0xFFF8
+ mov sp, dx
+ mov bp, dx
+
+ mov [si-0x0001], cs
+ add ax, 0x0A
+ mov [si-0x0003], ax
+ mov dl, 0xFA
+ mov [si-0x0007], dx
+ mov dl, 0x5A
+ mov [si-0x0005], dl
+ mov dl, 0xCB
+ mov [si-0x0004], dl
+
+ jmp 0x0050:0x0000
+;--------------------------------------------------
+char_vga_setbios:
+ mov cx, bx ; preserve bx
+ mov ah, 0x0f
+ int 0x10 ; bh is set by int 0x10, ah=0x0f
+ mov ah, 0x02
+ int 0x10
+ mov bx, cx ; restore bx
+ ret
+
+char_vga_savebios:
+ mov cx, bx ; preserve bx
+ mov ah, 0x0f
+ int 0x10 ; bh is set by int 0x10, ah=0x0f
+ mov ah, 0x03
+ int 0x10
+ mov bx, cx ; restore bx
+ ret
+
+putintbuf: times 5 db 0
diff --git a/reader.c b/reader.c new file mode 100644 index 0000000..7b30c1f --- /dev/null +++ b/reader.c @@ -0,0 +1,49 @@ +#include <yotlibc.h> + +short rval = 8; +short abc[100]; +int main(void){ + XYCOORD xys; + short k; + extern int char_vga_cursor_x; + extern int char_vga_cursor_y; + int i; +// xys.x = 1; +// xys.y = 1; +// chv_set_cursor(&xys); +// char_vga_tobios(); +// putint(char_vga_cursor_x); +// putint(char_vga_cursor_y); + chv_init_cursor(); + chv_memwrite(5, 4); + xys.y = 23; + xys.x = 4; + chv_set_cursor(&xys); + putint(char_vga_cursor_y); + for(i=0; i<9; i++){ + chv_putchar('F'); + } + chv_sync_cursor(); + yotrl(abc, "", 99); + putstr(abc); +// chv_putchar_color('A', CHV_COLORPAIR(CHV_COLOR_GREEN, CHV_COLOR_GRAY)); +// chv_backspace(); +// chv_scroll(25); +// chv_clear(); +// chv_reset_cursor(); +// chv_sync_cursor(); +// chv_putchar('A'); +// char_vga_tobios(); +// putint(22); +// putint(chv_memread(5)); +// putstr("PPP"); + //putstr("KKK:"); + /*while(1){ + int a = getch(); + a = GETCH_SCANCODE(a); + putcharhex(a); + } + putint(getstr(abc, 10)); + putstr(abc);*/ + return 0xFFFD; +} diff --git a/yotlibc/Makefile b/yotlibc/Makefile new file mode 100644 index 0000000..ebdc45c --- /dev/null +++ b/yotlibc/Makefile @@ -0,0 +1,18 @@ + +.PHONY: all clean +.SUFFIXES: .c.o .s.o + +OBJ=bccfunc.o str_out.o char_in.o str_in.o char_vga.o char_vhl.o + +all: yotlibc.a + +yotlibc.a: $(OBJ) + ar86 rc $@ $(OBJ) + +.s.o: + nasm -f as86 $< -o $@ +.c.o: + bcc -ansi -Mc -c $< -o $@ + +clean: + rm -f yotlibc.a $(OBJ) diff --git a/yotlibc/bccfunc.s b/yotlibc/bccfunc.s new file mode 100644 index 0000000..3060428 --- /dev/null +++ b/yotlibc/bccfunc.s @@ -0,0 +1,9 @@ +; 專門給 bcc 用的,我不知道為什麼它會缺基本功能 + +global imod + +imod: + cwd + idiv bx + mov ax,dx + ret diff --git a/yotlibc/char_in.s b/yotlibc/char_in.s new file mode 100644 index 0000000..03fb29d --- /dev/null +++ b/yotlibc/char_in.s @@ -0,0 +1,12 @@ +global _getch +global getch + +_getch: + push bp + mov bp, sp + mov ah, 0x0 + int 0x16 + mov sp, bp + pop bp + ret + diff --git a/yotlibc/char_vga.s b/yotlibc/char_vga.s new file mode 100644 index 0000000..6ac1c20 --- /dev/null +++ b/yotlibc/char_vga.s @@ -0,0 +1,141 @@ +global _char_vga_get_cursor +global _char_vga_set_cursor +global _char_vga_tobios +global _char_vga_frombios +global _char_vga_memread ; NOT A FUNCTION! +global _char_vga_memwrite ; NOT A FUNCTION! +global _char_vga_cursor_x +global _char_vga_cursor_y + +global _chv_memread +global _chv_memwrite + +_char_vga_cursor_x: dw 0 +_char_vga_cursor_y: dw 0 + +_char_vga_get_cursor: + push bp + mov bp, sp + xor cx, cx ; cx=result + + mov dx, 0x3D4 + mov al, 0x0E + out dx, al ; read high byte + + mov dx, 0x3D5 + in al, dx + mov ch, al + + mov dx, 0x3D4 + mov al, 0x0F + out dx, al ; read low byte + + mov dx, 0x3D5 + in al, dx + mov cl, al + + mov ax, cx ; set return value + + mov sp, bp + pop bp + ret + + +_char_vga_set_cursor: + push bp + mov bp, sp + mov cx, [bp+4] ; cx=argument + + mov dx, 0x3D4 + mov al, 0x0E + out dx, al ; send high byte + + mov dx, 0x3D5 + mov al, ch + out dx, al + + mov dx, 0x3D4 + mov al, 0x0F + out dx, al ; send low byte + + mov dx, 0x3D5 + mov al, cl + out dx, al + + mov sp, bp + pop bp + ret + +_char_vga_tobios: + push bp + mov bp, sp + + mov cx, bx ; preserve bx + + mov ah, 0x0f + int 0x10 ; bh is set by int 0x10, ah=0x0f + mov dl, [_char_vga_cursor_x] + mov dh, [_char_vga_cursor_y] + mov ah, 0x02 + int 0x10 + + mov bx, cx ; restore bx + + mov sp, bp + pop bp + ret + +_char_vga_frombios: + push bp + mov bp, sp + + mov cx, bx ; preserve bx + + mov ah, 0x0f + int 0x10 ; bh is set by int 0x10, ah=0x0f + mov [_char_vga_cursor_x], dl + mov [_char_vga_cursor_y], dh + mov ah, 0x03 + int 0x10 + + mov bx, cx ; restore bx + + mov sp, bp + pop bp + ret + +_char_vga_memread: ; al=result, bx=addr + mov dx, 0xb800 + mov fs, dx + mov al, [fs:bx] + ret + +_char_vga_memwrite: ; al=value, bx=addr + mov dx, 0xb800 + mov fs, dx + mov [fs:bx], al + ret + +_chv_memread: + push bp + mov bp,sp + + mov bx, [bp+4] + call _char_vga_memread + xor ah, ah + + mov sp, bp + pop bp + ret + +_chv_memwrite: + push bp + mov bp,sp + + mov bx, [bp+4] + mov al, [bp+6] + call _char_vga_memwrite + + mov sp, bp + pop bp + ret diff --git a/yotlibc/char_vhl.c b/yotlibc/char_vhl.c new file mode 100644 index 0000000..2cab8db --- /dev/null +++ b/yotlibc/char_vhl.c @@ -0,0 +1,149 @@ +/* char_vhl = char VGA high level function */ + +#include "yotlibc.h" + +extern int char_vga_cursor_x; +extern int char_vga_cursor_y; + +void chv_init_cursor(void){ + int curpos = char_vga_get_cursor(); + char_vga_cursor_x = CHAR_VGA_GETX(curpos); + char_vga_cursor_y = CHAR_VGA_GETY(curpos); +} + +void chv_get_cursor(xycoord) + XYCOORD* xycoord; +{ + chv_init_cursor(); + xycoord->x = char_vga_cursor_x; + xycoord->y = char_vga_cursor_y; +} + +void chv_set_cursor(xycoord) + XYCOORD* xycoord; +{ + char_vga_cursor_x = xycoord->x; + char_vga_cursor_y = xycoord->y; + char_vga_set_cursor( + CHAR_VGA_POSITION(char_vga_cursor_x, char_vga_cursor_y)); +} + +void chv_set_cursor_direct(x, y) + int x; + int y; +{ + char_vga_cursor_x = x; + char_vga_cursor_y = y; + char_vga_set_cursor( + CHAR_VGA_POSITION(char_vga_cursor_x, char_vga_cursor_y)); +} + +void chv_sync_cursor(void){ + char_vga_set_cursor( + CHAR_VGA_POSITION(char_vga_cursor_x, char_vga_cursor_y)); +} + +void chv_reset_cursor(void){ + chv_set_cursor_direct(0, 0); +} + +void chv_movenext_cursor(void){ + if(++char_vga_cursor_x >= CHAR_VGA_SCREENX){ + char_vga_cursor_x -= CHAR_VGA_SCREENX; + char_vga_cursor_y++; + } + if(char_vga_cursor_y >= CHAR_VGA_SCREENY){ + char_vga_cursor_y = CHAR_VGA_SCREENY; + chv_scroll(1); + } +} + +void chv_moveprev_cursor(void){ + if(--char_vga_cursor_x < 0){ + char_vga_cursor_x += CHAR_VGA_SCREENX; + char_vga_cursor_y--; + } + if(char_vga_cursor_y < 0){ + char_vga_cursor_y = 0; + } +} + +void chv_move_cursor(count) + int count; +{ + int n; + n = CHAR_VGA_POSITION(char_vga_cursor_x, char_vga_cursor_y) + count; + char_vga_cursor_x = CHAR_VGA_GETX(n); + char_vga_cursor_y = CHAR_VGA_GETY(n); + if(char_vga_cursor_x > CHAR_VGA_SCREENX){ + char_vga_cursor_x = CHAR_VGA_SCREENX - 1; + }else if(char_vga_cursor_x < 0){ + char_vga_cursor_x = 0; + } + if(char_vga_cursor_y > CHAR_VGA_SCREENY){ + char_vga_cursor_y = CHAR_VGA_SCREENY - 1; + }else if(char_vga_cursor_y < 0){ + char_vga_cursor_y = 0; + } +} + +void chv_putchar(c) + int c; +{ + chv_memwrite( + CHAR_VGA_POSITION(char_vga_cursor_x, char_vga_cursor_y) * 2, c); + chv_movenext_cursor(); +} + +void chv_putchar_color(c, color) + int c; + int color; +{ + int pos = CHAR_VGA_POSITION(char_vga_cursor_x, char_vga_cursor_y) * 2; + chv_memwrite(pos++, c); + chv_memwrite(pos, color); + chv_movenext_cursor(); +} + +void chv_backspace(void){ + chv_moveprev_cursor(); + chv_memwrite( + CHAR_VGA_POSITION(char_vga_cursor_x, char_vga_cursor_y) * 2, ' '); +} + +void chv_clear(void){ + int i; + XYCOORD xycoord; + chv_memwrite(0, 'A'); + for(i=0; i< CHAR_VGA_MMIOSIZE; ){ + chv_memwrite(i++, ' '); + chv_memwrite(i++, CHV_COLORPAIR( + CHV_COLOR_LIGHT_GRAY, CHV_COLOR_BLACK)); + } +} + +void chv_scroll(line) + int line; +{ + int c, i; + int src, dest; + if(line > 0){ + src = line * CHAR_VGA_SCREENX * 2; + for(dest = 0; dest < CHAR_VGA_MMIOSIZE && src < CHAR_VGA_MMIOSIZE; + dest++, src++){ + c = chv_memread(src); + chv_memwrite(dest, c); + } + for(; dest < CHAR_VGA_MMIOSIZE; ){ + chv_memwrite(dest++, ' '); + chv_memwrite(dest++, CHV_COLORPAIR( + CHV_COLOR_LIGHT_GRAY, CHV_COLOR_BLACK)); + } + char_vga_cursor_y -= line; + if(char_vga_cursor_y < 0){ + char_vga_cursor_y = 0; + chv_sync_cursor(); + } + } +} + diff --git a/yotlibc/str_in.c b/yotlibc/str_in.c new file mode 100644 index 0000000..529b7ab --- /dev/null +++ b/yotlibc/str_in.c @@ -0,0 +1,279 @@ +#include "yotlibc.h" + +int getstr(dest, maxlen) + char* dest; + int maxlen; +{ + int c, cascii, cscan; + int i = 0, j; + extern int char_vga_cursor_x; + extern int char_vga_cursor_y; + + chv_init_cursor(); + + for(;;){ + c = getch(); + cascii = GETCH_ASCII(c); + cscan = GETCH_SCANCODE(c); + if(cascii >= 32 && cascii < 128){ + if(i < maxlen){ + dest[i++] = cascii; + chv_putchar(cascii); + chv_sync_cursor(); + } + }else{ + switch(cscan){ + case KEYDOWN_SCANCODE_ENTER: + dest[i++] = '\0'; + char_vga_cursor_y++; + char_vga_cursor_x = 0; + chv_sync_cursor(); + char_vga_tobios(); + return i; + case KEYDOWN_SCANCODE_BS: + if(i <= 0){ + continue; + } + dest[i--] = '\0'; + chv_backspace(); + chv_sync_cursor(); + break; + case KEYDOWN_SCANCODE_ESC: + chv_move_cursor(-i); + for(j=0; j<i; j++){ + chv_putchar(' '); + } + chv_move_cursor(-i); + chv_sync_cursor(); + i = 0, dest[0] = '\0'; + break; + + } + } + } + return 0; +} + +int yotrl(dest, init, maxlen) + char* dest; + char* init; + int maxlen; +{ + int c, cascii, cscan; + int pos = 0, nowlen = 0, i; + char* ip; + int blank; + char prechar; + extern int char_vga_cursor_x; + extern int char_vga_cursor_y; + XYCOORD xy; + + chv_init_cursor(); + + if(init != NULL){ + for(i=0; i<maxlen && init[i] != '\0'; i++){ + dest[i] = init[i]; + } + dest[i] = '\0'; + pos = i, nowlen = i; + for(ip = dest; *ip != '\0'; ip++){ + chv_putchar(*ip); + } + } + + chv_sync_cursor(); + + for(;;){ + c = getch(); + cascii = GETCH_ASCII(c); + cscan = GETCH_SCANCODE(c); + /* 判斷規則:正常輸入 -> scan code -> ASCII code 控制鍵 */ + if(cascii >= 32 && cascii < 128){ + if(nowlen + 1 <= maxlen){ + if(pos == nowlen){ + dest[pos++] = cascii; + nowlen++; + chv_putchar(cascii); + chv_sync_cursor(); + }else{ + xy.x = char_vga_cursor_x; + xy.y = char_vga_cursor_y; + for(i=nowlen; i>pos; i--){ + dest[i] = dest[i-1]; + } + dest[pos] = cascii; + chv_putchar(cascii); + nowlen++, pos++; + for(i=pos; i<nowlen; i++){ + chv_putchar(dest[i]); + } + char_vga_cursor_x = xy.x; + char_vga_cursor_y = xy.y; + chv_movenext_cursor(); + chv_sync_cursor(); + } + } + }else{ + switch(cscan){ + case KEYDOWN_SCANCODE_ENTER: + dest[nowlen++] = '\0'; + char_vga_cursor_y++; + char_vga_cursor_x = 0; + chv_sync_cursor(); + char_vga_tobios(); + return nowlen; + case KEYDOWN_SCANCODE_LEFT: + if(pos > 0){ + pos--; + chv_moveprev_cursor(); + chv_sync_cursor(); + } + continue; + case KEYDOWN_SCANCODE_RIGHT: + if(pos < nowlen){ + pos++; + chv_movenext_cursor(); + chv_sync_cursor(); + } + continue; + case KEYDOWN_SCANCODE_BS: + if(pos <= 0){ + continue; + } + if(pos == nowlen){ + dest[pos--] = '\0'; + nowlen--; + chv_backspace(); + chv_sync_cursor(); + }else{ + chv_moveprev_cursor(); + xy.x = char_vga_cursor_x; + xy.y = char_vga_cursor_y; + for(i=pos; i<nowlen; i++){ + dest[i-1] = dest[i]; + } + pos--, nowlen--; + for(i=pos; i<nowlen; i++){ + chv_putchar(dest[i]); + } + chv_putchar(' '); + char_vga_cursor_x = xy.x; + char_vga_cursor_y = xy.y; + chv_sync_cursor(); + } + continue; + case KEYDOWN_SCANCODE_DELETE: + if(pos >= nowlen){ + continue; + } + xy.x = char_vga_cursor_x; + xy.y = char_vga_cursor_y; + for(i=pos; i<nowlen; i++){ + dest[i] = dest[i+1]; + } + nowlen--; + for(i=pos; i<nowlen; i++){ + chv_putchar(dest[i]); + } + chv_putchar(' '); + char_vga_cursor_x = xy.x; + char_vga_cursor_y = xy.y; + chv_sync_cursor(); + continue; + case KEYDOWN_SCANCODE_HOME: + cascii = 1; /* 與 Ctrl+A 相同*/ + break; + case KEYDOWN_SCANCODE_END: + cascii = 5; /* 與 Ctrl+E 相同 */ + break; + case KEYDOWN_SCANCODE_ESC: + cascii = 3; /* 與 Ctrl+C 相同 */ + break; + } + + switch(cascii){ + case 1: /* Ctrl+A */ + chv_move_cursor(-pos); + chv_sync_cursor(); + pos = 0; + break; + case 3: /* Ctrl+C */ + chv_move_cursor(-pos); + for(i=0; i<nowlen; i++){ + chv_putchar(' '); + } + chv_move_cursor(-nowlen); + chv_sync_cursor(); + nowlen = 0, pos = 0; + break; + case 5: /* Ctrl+E */ + chv_move_cursor(nowlen - pos); + chv_sync_cursor(); + pos = nowlen; + break; + case 11: /* Ctrl+K */ + blank = nowlen - pos; + xy.x = char_vga_cursor_x; + xy.y = char_vga_cursor_y; + for(i=0; i<blank; i++){ + chv_putchar(' '); + } + nowlen = pos; + char_vga_cursor_x = xy.x; + char_vga_cursor_y = xy.y; + chv_sync_cursor(); + break; + case 21: /* Ctrl+U */ + blank = pos; + for(i=pos; i<nowlen; i++){ + dest[i-blank] = dest[i]; + } + chv_move_cursor(-pos); + xy.x = char_vga_cursor_x; + xy.y = char_vga_cursor_y; + pos = 0; + nowlen -= blank; + for(i=0; i<nowlen; i++){ + chv_putchar(dest[i]); + } + for(i=0; i<blank; i++){ + chv_putchar(' '); + } + char_vga_cursor_x = xy.x; + char_vga_cursor_y = xy.y; + chv_sync_cursor(); + break; + case 23: /* Ctrl+W */ + if(pos == 0){ + break; + } + for(i=pos-1; i>=0 && dest[i] == ' '; i--); + for(; i>=0 && dest[i] != ' '; i--); + i++; + blank = pos - i; + if(i < blank){ + i = blank; + } + for(i=pos; i<nowlen; i++){ + dest[i-blank] = dest[i]; + } + pos -= blank; + nowlen -= blank; + chv_move_cursor(-blank); + xy.x = char_vga_cursor_x; + xy.y = char_vga_cursor_y; + for(i=pos; i<nowlen; i++){ + chv_putchar(dest[i]); + } + for(i=0; i<blank; i++){ + chv_putchar(' '); + } + char_vga_cursor_x = xy.x; + char_vga_cursor_y = xy.y; + chv_sync_cursor(); + break; + } + } + } + return 0; +} diff --git a/yotlibc/str_out.s b/yotlibc/str_out.s new file mode 100644 index 0000000..202d808 --- /dev/null +++ b/yotlibc/str_out.s @@ -0,0 +1,98 @@ +global _putint +global putcharhex +global _putcharhex +global putstr +global _putstr + +_putint: + push bp + mov bp, sp + mov ax, word [bp+4] ; ax=argument + sub sp, 8 ; 5 bytes - printing buffer + pusha + mov di, -1 ; dest index + mov si, 10 ; divisor, ax=dividend +putint_divloop: + mov dx, 0 ; clear upper bits + div si + add dx, '0' + mov byte [bp+di], dl + dec di + cmp ax, 0 + ja putint_divloop + + mov ah, 0x0e + mov bx, 0x0007 +putint_print: + inc di + mov al, byte [bp+di] + int 0x10 + cmp di, -1 + jl putint_print + + popa + mov sp, bp + pop bp + ret + + +_putcharhex: + push bp + mov bp, sp + mov cl, byte [bp+4] + call putcharhex + mov sp, bp + pop bp + ret + +putcharhex: ; cl=argument + mov dx, bx ; preserve bx + mov ah, 0x0e + mov bx, 0x0007 + mov al, cl + and al, 0xf0 + shr al, 4 + call fourbit2hex + int 0x10 + mov al, cl + and al, 0x0f + call fourbit2hex + int 0x10 + mov bx, dx ; restore bx + ret + +fourbit2hex: ; al=argument=result + cmp al, 10 + jae fourbit2hex_alpha + add al, '0' + ret +fourbit2hex_alpha: + add al, 'A' - 10 + ret + + +_putstr: + push bp + mov bp, sp + mov dx, word [bp+4] + call putstr + mov sp, bp + pop bp + ret + +putstr: ; dx=argument + mov cx, bx ; we must preserve bx +putstr_start: + mov bx, dx ; [dx] is not a effective address + mov al, byte [bx] + test al, al + jz putstr_end + mov ah, 0x0e + mov bx, 0x0007 + int 0x10 + inc dx + jmp putstr_start +putstr_end: + mov bx, cx + ret + diff --git a/yotlibc/yotlibc.h b/yotlibc/yotlibc.h new file mode 100644 index 0000000..1d9e5ca --- /dev/null +++ b/yotlibc/yotlibc.h @@ -0,0 +1,153 @@ +#ifndef YOT_OS_LIBC16 +#define YOT_OS_LIBC16 + +#ifndef NULL +#define NULL ((char*)0) +#endif + +#ifndef EOF +#define EOF (-1) +#endif + +#ifndef bool +#define bool char +#endif + +#ifndef true +#define true 1 +#endif + +#ifndef false +#define false 0 +#endif + +#define exit(globalvar) \ + asm "mov sp, bp"; \ + asm "mov ax, [_" #globalvar "]" ; \ + asm "pop bp"; \ + asm "retf" + +/* str_out.s */ +void putint(unsigned short); /* 以 10 進位顯示一個 word (unsigned) */ +void putcharhex(char); /* 以 16 進位顯示一個 byte */ +void putstr(const char*); /* 顯示一個字串,'\0' 是結束 */ + +/* char_in.s */ +#define GETCH_SCANCODE(code16) (((code16) & 0xff00) >> 8) +#define GETCH_ASCII(code16) ((code16) & 0x00ff) +int getch(void); + +/* char_vga.s + char_vhl.c */ +#define CHAR_VGA_POSITION(x,y) (((y)*80)+(x)) +#define CHAR_VGA_GETX(n) ((n)%80) +#define CHAR_VGA_GETY(n) ((n)/80) +#define CHAR_VGA_SCREENX 80 +#define CHAR_VGA_SCREENY 25 +#define CHAR_VGA_SCREENSIZE ((CHAR_VGA_SCREENX)*(CHAR_VGA_SCREENY)) +#define CHAR_VGA_MMIOSIZE ((CHAR_VGA_SCREENSIZE)*2) + +#define CHV_COLORPAIR(fg,bg) ((fg) | ((bg) << 4)) +#define CHV_COLOR_BLACK 0 +#define CHV_COLOR_BLUE 1 +#define CHV_COLOR_GREEN 2 +#define CHV_COLOR_CYAN 3 +#define CHV_COLOR_RED 4 +#define CHV_COLOR_MAGENTA 5 +#define CHV_COLOR_BROWN 6 +#define CHV_COLOR_LIGHT_GRAY 7 +#define CHV_COLOR_GRAY 8 +#define CHV_COLOR_LIGHT_BLUE 9 +#define CHV_COLOR_LIGHT_GREEN 10 +#define CHV_COLOR_LIGHT_CYAN 11 +#define CHV_COLOR_LIGHT_RED 12 +#define CHV_COLOR_LIGHT_MAGNETA 13 +#define CHV_COLOR_LIGHT_BROWN 14 +#define CHV_COLOR_WHITE 15 + +typedef struct char_vga_position{ + int x, y; +} XYCOORD; + +void chv_init_cursor(void); +void chv_sync_cursor(void); +void chv_reset_cursor(void); +void chv_get_cursor(XYCOORD*); +void chv_set_cursor(const XYCOORD*); +void chv_set_cursor_direct(int, int); +void chv_movenext_cursor(void); +void chv_moveprev_cursor(void); +void chv_move_cursor(int); +void chv_putchar(int); +void chv_putchar_color(int, int); +void chv_backspace(void); +void chv_clear(void); +void chv_scroll(int); +char chv_memread(int); +void chv_memwrite(int, char); + +#define chv_screen_write_char(position,character) \ + chv_memwrite(((position)*2), (character)) +#define chv_screen_write_color(position,color) \ + chv_memwrite(((position)*2+1), (color)) + +int char_vga_get_cursor(void); +void char_vga_set_cursor(int); +void char_vga_frombios(void); +void char_vga_tobios(void); + +/* keyboard scan codes */ +#define KEYDOWN_SCANCODE_ESC 0x01 +#define KEYDOWN_SCANCODE_BS 0x0e +#define KEYDOWN_SCANCODE_TAB 0x0f +#define KEYDOWN_SCANCODE_ENTER 0x1c +#define KEYDOWN_SCANCODE_CTRL 0x1d +#define KEYDOWN_SCANCODE_LEFT_SHIFT 0x2a +#define KEYDOWN_SCANCODE_RIGHT_SHIFT 0x36 +#define KEYDOWN_SCANCODE_PRINT_SCREEN 0x37 +#define KEYDOWN_SCANCODE_ALT 0x38 +#define KEYDOWN_SCANCODE_SPACE 0x39 +#define KEYDOWN_SCANCODE_CAPS_LOCK 0x3a +#define KEYDOWN_SCANCODE_FUNCTION(n) (0x3a+(n)) /* F1 ~ F10,其他不適用 */ +#define KEYDOWN_SCANCODE_NUM_LOCK 0x45 +#define KEYDOWN_SCANCODE_SCROLL_LOCK 0x46 +#define KEYDOWN_SCANCODE_HOME 0x47 +#define KEYDOWN_SCANCODE_UP 0x48 +#define KEYDOWN_SCANCODE_PAGE_UP 0x49 +#define KEYDOWN_SCANCODE_LEFT 0x4b +#define KEYDOWN_SCANCODE_RIGHT 0x4d +#define KEYDOWN_SCANCODE_END 0x4f +#define KEYDOWN_SCANCODE_DOWN 0x50 +#define KEYDOWN_SCANCODE_PAGE_DOWN 0x51 +#define KEYDOWN_SCANCODE_INSERT 0x52 +#define KEYDOWN_SCANCODE_DELETE 0x53 + +/* keypad */ +#define KEYDOWN_SCANCODE_KEYPAD_ENTER 0x1c +#define KEYDOWN_SCANCODE_KEYPAD_SLASH 0x35 +#define KEYDOWN_SCANCODE_KEYPAD_STAR 0x37 +#define KEYDOWN_SCANCODE_KEYPAD_7 0x47 +#define KEYDOWN_SCANCODE_KEYPAD_8 0x48 +#define KEYDOWN_SCANCODE_KEYPAD_9 0x49 +#define KEYDOWN_SCANCODE_KEYPAD_MINUS 0x4a +#define KEYDOWN_SCANCODE_KEYPAD_4 0x4b +#define KEYDOWN_SCANCODE_KEYPAD_5 0x4c +#define KEYDOWN_SCANCODE_KEYPAD_6 0x4d +#define KEYDOWN_SCANCODE_KEYPAD_ADD 0x4e +#define KEYDOWN_SCANCODE_KEYPAD_1 0x4f +#define KEYDOWN_SCANCODE_KEYPAD_2 0x50 +#define KEYDOWN_SCANCODE_KEYPAD_3 0x51 +#define KEYDOWN_SCANCODE_KEYPAD_0 0x52 +#define KEYDOWN_SCANCODE_KEYPAD_DOT 0x53 + +/* str_in.c */ +int getstr(char*, int); +/* 讀入一行的函式 + * ARG1 = 要存到哪裡 + * ARG2 = 最多可以讀多長('\0' 不計入,但要自行保留空間) + * RVAL = 實際讀了幾個字 */ + +int yotrl(char*, const char*, int); +/* 同上,但是是進階版 */ + +#endif + diff --git a/yotlibc/yotlibc.txt b/yotlibc/yotlibc.txt new file mode 100644 index 0000000..3e27cfc --- /dev/null +++ b/yotlibc/yotlibc.txt @@ -0,0 +1,140 @@ + +1 基本功能 + +-- 插斷: int 0x50: 關機. (好像不是yotlibc XD") +-- Macro: void exit(全域變數) 取消. + + +2 輸出(透過 BIOS) + +-- Function: void putint(unsigned short 數字) + 以 10 進位顯示一個 16-bit 無號整數 + +-- Function: void putcharhex(char 位元組) + 以 16 進位顯示一個位元組的值 + +-- Function: void putstr(const char* 字串) + 顯示字串(不會自動加上 '\n') + + +3 讀入一個按鍵 + +-- Function: int getch(void) + 等待使用者按鍵,回傳按鍵的 scan code 與 ASCII code + +-- Macro: int GETCH_SCANCODE(int 按鍵值) + 取出 getch() 回傳值的 scan code 部份 + +-- Macro: int GETCH_ASCII(int 按鍵值) + 取出 getch() 回傳值的 ASCII code 部份 + + +4 螢幕輸出控制(除了部份與 BIOS 相容的函式外,這些函式並不依賴 BIOS) + +-- Data Type: XYCOORD + 儲存座標 + +-- Macro: int CHAR_VGA_POSITION(int x, int y) + 將 x 與 y 座標轉成單一整數 + +-- Macro: int CHAR_VGA_GETX(int n) + 將轉為單一整數後的座標的 x 部份取出 + +-- Macro: int CHAR_VGA_GETY(int n) + 將轉為單一整數後的座標的 y 部份取出 + +-- Constant: int CHAR_VGA_SCREENX + 定義螢幕行數 + +-- Constant: int CHAR_VGA_SCREENY + 定義螢幕列數 + +-- Constant: int CHAR_VGA_SCREENSIZE + 定義螢幕總字數 + +-- Constant: int CHAR_VGA_MMIOSIZE + VGA memory-mapped I/O 在記憶體中佔的總位元組數 + +-- Macro: int CHV_COLORPAIR(int 前景, int 背景) + 產生前景、背景顏色對數值 + +-- Variable: int char_vga_cursor_x + 儲存目前游標位置的 x 座標 + +-- Variable: int char_vga_cursor_y + 儲存目前游標位置的 y 座標 + +-- Function: void chv_init_cursor(void) + 將目前游標位址存入全域變數 + 第一次使用或是使用其他類型函式(包含 BIOS 或是 put 開頭的函式)變游標位址 + 時,必須先執行這個函式 + +-- Function: void chv_sync_cursor(void) + 執行游標移動。所有游標移動函式(chv_set_cursor、chv_set_cursor_direct、 + chv_reset_cursor 除外)只會更改變數值,必須執行此函式才會真正移動游標 + +-- Function: void chv_reset_cursor(void) + 將游標移回左上角 + +-- Function: void chv_get_cursor(XYCOORD* 回傳的位址) + 透過 I/O 取得游標位址 + +-- Function: void chv_set_cursor(XYCOORD* 要設定的位址) + 立即移動游標 + +-- Function: void chv_set_cursor_direct(int x, int y) + 同上,只是不需要準備一個 struct + +-- Function: void chv_movenext_cursor(void) + 游標移到後一格,換行、螢幕捲動的問題會自動處理 + +-- Function: void chv_moveprev_cursor(void) + 游標移到前一格,行的問題會自動處理 + +-- Function: void chv_move_cursor(int 格子數量) + 游標大量向後移動(指定負數可向前移動) + +-- Function: void chv_putchar(int 字元) + 顯示一個字元(游標自動後移) + +-- Function: void chv_putchar_color(int 字元, int 顏色) + 同上,多了指定顏色的功能 + +-- Function: void chv_backspace(void) + 清除目前所在位置的字元並倒退一格 + +-- Function: void chv_clear(void) + 清空整個螢幕 + +-- Function: void chv_scroll(int 行數) + 螢幕捲動 + +-- Function: char chv_memread(int 位置) + 自 0xB8000+位置 讀回一個位元組 + +-- Function: void chv_memwrite(int 位置, char 字元) + 向 0xB8000+位置 寫入一個位元組 + +-- Macro: void chv_screen_write_char(int 位置, int 字元) + 替換此位置的字元 + +-- Macro: void chv_screen_write_color(int 位置, int 顏色) + 替換此位置字元的顏色 + +-- Function: void char_vga_get_cursor(void) + void char_vga_set_cursor(int 位置) + 內部運作的函式,我不多做解釋 + +-- Function: void char_vga_frombios(void) + 透過 BIOS 讀回目前游標位置 + +-- Function: void char_vga_tobios(void) + 透過 BIOS 移動目前游標位置 + + +5 字串輸入 + +-- Function: int getstr(char* 字串, int 字串最大長度) + ARG1 = 要存到哪裡 + ARG2 = 最多可以讀多長('\0' 不計入,但要自行保留空間) + RVAL = 實際讀了幾個字 |