Auteur | SHA1 | Message | Date |
---|---|---|---|
Jakob Kjær-Kammersgaard | 35edf789e5 | minize | il y a 5 ans |
Jakob Kjær-Kammersgaard | dafa6183ef | . | il y a 5 ans |
Jakob Kjær-Kammersgaard | 1a3e8f7649 | godnat | il y a 5 ans |
Jakob Kjær-Kammersgaard | 41d4b4a7fb | PROTECTED MODE BABY | il y a 5 ans |
Jakob Kjær-Kammersgaard | 15894ab4c6 | Lets32Bit | il y a 6 ans |
@ -1,5 +0,0 @@ | |||
.DS_Store | |||
*.swp | |||
*.sublime* | |||
*.img | |||
*.bin |
@ -1,173 +0,0 @@ | |||
BITS 16 | |||
;CLI | |||
;Command syntax: <command name> <arg1> | |||
;Argument must not contain spaces. | |||
; Data | |||
CLI_Command_Buffer times 256 db 0 | |||
CLI_Command_Length dw 0 | |||
; API | |||
; args: | |||
; ax: keyboard keycode. | |||
CLI_ASCII_INPUT: | |||
pusha | |||
; Fetch command buffer offset. | |||
; If there is no room in the buffer, then just bail on the key press. | |||
mov bx, [CLI_Command_Length] | |||
cmp bx, 255 | |||
je .end | |||
inc bx ; The new last element will be located at this offset. | |||
mov [CLI_Command_Length], bx ; Save the new counter. | |||
dec bx ; Go back to the index the character should be written to. | |||
; Move new ascii character into command buffer. | |||
add bx, CLI_Command_Buffer ; address+offset = destination | |||
mov [bx], al | |||
inc bx | |||
mov byte [bx], 0 | |||
; Print out the input character | |||
mov ah, 0xe ; Teletype output | |||
mov bl, 0x02 ; color (green) | |||
int 0x10 | |||
.end: | |||
popa | |||
ret | |||
; args: | |||
CLI_DELETE: | |||
pusha | |||
; Check if at the beginning of the line. | |||
mov bx, [CLI_Command_Length] | |||
cmp bx, 0x00 | |||
je .end | |||
; Move the counter one back | |||
sub bx, 0x01 | |||
mov [CLI_Command_Length], bx | |||
;Move NULL into the last character of the line (delete) | |||
mov al, 0x0 | |||
add bx, CLI_Command_Buffer ; address+offset = destination | |||
mov [bx], al | |||
; Go back one space | |||
mov ax, 0x0e08 ; ah=0x0e means teletype output. al=0x08 means backspace character. | |||
int 0x10 | |||
; Place a NULL | |||
mov al, 0x0 ; NULL | |||
int 0x10 | |||
; Go back one space again as the above print of NULL pushes the cursor forward again. | |||
mov ax, 0x0e08 | |||
int 0x10 | |||
.end: | |||
popa | |||
ret | |||
; Probably activated with the 'Enter' button. | |||
CLI_CONFIRM_INPUT: | |||
call CLI_EXECUTE | |||
mov bx, 0 | |||
mov [CLI_Command_Length], bx | |||
mov [CLI_Command_Buffer], bx | |||
ret | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
print_help_message: | |||
; Prints a list of available commands | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
push si | |||
mov si, .command_list_string | |||
call print | |||
pop si | |||
ret | |||
.command_list_string: | |||
db 13, 10 | |||
db "Available commands:", 13, 10 | |||
db " help: Prints this screen", 13, 10 | |||
db " dumpmem: Prints the contents of a memory region (At the moment hardcoded)", 13, 10 | |||
db " keyprint: Prints the character and keycode for a key presssd", 13, 10 | |||
db " clear: Clears the screen", 13, 10 | |||
db " formatdisk: Initialize the file system", 13, 10 | |||
db " createfile: Name a file, in the file system", 13, 10 | |||
db " fsinfo: Displays info about the file system", 13, 10 | |||
db " ls: Lists the named files", 13, 10 | |||
db " svim: SingOS' text editor", 13, 10, 0 | |||
; Executes the command. | |||
CLI_EXECUTE: | |||
pusha | |||
mov bx, [CLI_Command_Length] | |||
cmp bx, 0 | |||
je near .end ; If there are not bytes in the buffer then there is no command. | |||
mov ax, [.Num_Commands] ; The number of commands available. | |||
lea si, [CLI_Command_Buffer] | |||
mov cx, 0 ; Index into the list of commands. | |||
.Interpreter_Search_Commands_Loop: | |||
;cmp cx, ax ; Start by comparing. | |||
;je .end | |||
mov bx, cx ; Move Index into bx to offset into the array of commands. | |||
add bx, bx ; The pointers are two bytes long. This compensates for that. | |||
mov bx, [.Command_Name_List + bx] ; Fetch the pointer for the string. | |||
lea di, [bx] | |||
call stringcompare | |||
je .Interpreter_Command_Execute | |||
inc cx ; Prepare for next iteration. | |||
cmp ax, cx | |||
je .end | |||
jmp .Interpreter_Search_Commands_Loop | |||
.Interpreter_Command_Execute: | |||
mov bx, cx ; Move Index into bx to offset into the array of commands. | |||
add bx, bx ; The pointers are two bytes long. This compensates for that. | |||
pusha | |||
call printCRLF | |||
popa | |||
mov dx, [.Command_Function_Pointers + bx] ; Program pointer | |||
; Execute program. | |||
call dx | |||
.end: | |||
popa | |||
ret | |||
.tmp dw 0 | |||
.Num_Commands dw 9 | |||
.Command_Name_List dw .CMD1, .CMD2, .CMD3, .CMD4, .CMD5, .CMD6, .CMD7, .CMD8, .CMD9 | |||
.Command_Function_Pointers dw dumpmem_hardcoded_args, keyprint, svim, vsfs_list_files_command, vsfs_create_file, vsfs_format_disk, vsfs_get_fs_info, os_clear_screen, print_help_message | |||
.CMD1 db 'dumpmem', 0 | |||
.CMD2 db 'keyprint', 0 | |||
.CMD3 db 'svim', 0 | |||
.CMD4 db 'ls', 0 | |||
.CMD5 db 'createfile', 0 | |||
.CMD6 db 'formatdisk', 0 | |||
.CMD7 db 'fsinfo', 0 | |||
.CMD8 db 'clear', 0 | |||
.CMD9 db 'help', 0 | |||
@ -1,39 +0,0 @@ | |||
SingOS is a single task operating system. | |||
Current version 0.0.3 | |||
The goal for this project is to create a Operating System | |||
which tries to find new better ways to handle memory adressing | |||
It will also be posible to switch between 16, 32 and 64-bit mode | |||
such that anything on very low level can be tested. | |||
You can build and run the OS with following command | |||
(Require nasm and qemu installed) | |||
```sh | |||
sh build.sh | |||
``` | |||
If you only want to run SingOS: | |||
```sh | |||
sh build.sh run | |||
``` | |||
If you only want to compile the binary: | |||
```sh | |||
sh build.sh make | |||
``` | |||
If you want to write it to a usb device | |||
```sh | |||
sudo dd if=/some_dir/SingOS.img of=/dev/name_device status=progress oflag=sync | |||
``` |
@ -0,0 +1,226 @@ | |||
Artiskok.bin: file format binary | |||
Disassembly of section .data: | |||
00000000 <.data>: | |||
0: eb 63 jmp 0x7c65 | |||
2: 90 nop | |||
3: 10 8e d0 bc adc BYTE PTR [bp-0x4330],cl | |||
7: 00 b0 b8 00 add BYTE PTR [bx+si+0xb8],dh | |||
b: 00 8e d8 8e add BYTE PTR [bp-0x7128],cl | |||
f: c0 fb be sar bl,0xbe | |||
12: 00 7c bf add BYTE PTR [si-0x41],bh | |||
15: 00 06 b9 00 add BYTE PTR ds:0xb9,al | |||
19: 02 f3 add dh,bl | |||
1b: a4 movs BYTE PTR es:[di],BYTE PTR ds:[si] | |||
1c: ea 21 06 00 00 jmp 0x0:0x621 | |||
21: be be 07 mov si,0x7be | |||
24: 38 04 cmp BYTE PTR [si],al | |||
26: 75 0b jne 0x33 | |||
28: 83 c6 10 add si,0x10 | |||
2b: 81 fe fe 07 cmp si,0x7fe | |||
2f: 75 f3 jne 0x24 | |||
31: eb 16 jmp 0x49 | |||
33: b4 02 mov ah,0x2 | |||
35: b0 01 mov al,0x1 | |||
37: bb 00 7c mov bx,0x7c00 | |||
3a: b2 80 mov dl,0x80 | |||
3c: 8a 74 01 mov dh,BYTE PTR [si+0x1] | |||
3f: 8b 4c 02 mov cx,WORD PTR [si+0x2] | |||
42: cd 13 int 0x13 | |||
44: ea 00 7c 00 00 jmp 0x0:0x7c00 | |||
49: eb fe jmp 0x49 | |||
4b: 00 00 add BYTE PTR [bx+si],al | |||
4d: 00 00 add BYTE PTR [bx+si],al | |||
4f: 00 00 add BYTE PTR [bx+si],al | |||
51: 00 00 add BYTE PTR [bx+si],al | |||
53: 00 00 add BYTE PTR [bx+si],al | |||
55: 00 00 add BYTE PTR [bx+si],al | |||
57: 00 00 add BYTE PTR [bx+si],al | |||
59: 00 00 add BYTE PTR [bx+si],al | |||
5b: 80 01 00 add BYTE PTR [bx+di],0x0 | |||
5e: 00 00 add BYTE PTR [bx+si],al | |||
60: 00 00 add BYTE PTR [bx+si],al | |||
62: 00 00 add BYTE PTR [bx+si],al | |||
64: ff (bad) | |||
65: fa cli | |||
66: 90 nop | |||
67: 90 nop | |||
68: f6 c2 80 test dl,0x80 | |||
6b: 74 05 je 0x72 | |||
6d: f6 c2 70 test dl,0x70 | |||
70: 74 02 je 0x74 | |||
72: b2 80 mov dl,0x80 | |||
74: ea 79 7c 00 00 jmp 0x0:0x7c79 | |||
79: 31 c0 xor ax,ax | |||
7b: 8e d8 mov ds,ax | |||
7d: 8e d0 mov ss,ax | |||
7f: bc 00 20 mov sp,0x2000 | |||
82: fb sti | |||
83: a0 64 7c mov al,ds:0x7c64 | |||
86: 3c ff cmp al,0xff | |||
88: 74 02 je 0x8c | |||
8a: 88 c2 mov dl,al | |||
8c: 52 push dx | |||
8d: be 80 7d mov si,0x7d80 | |||
90: e8 17 01 call 0x1aa | |||
93: be 05 7c mov si,0x7c05 | |||
96: b4 41 mov ah,0x41 | |||
98: bb aa 55 mov bx,0x55aa | |||
9b: cd 13 int 0x13 | |||
9d: 5a pop dx | |||
9e: 52 push dx | |||
9f: 72 3d jb 0xde | |||
a1: 81 fb 55 aa cmp bx,0xaa55 | |||
a5: 75 37 jne 0xde | |||
a7: 83 e1 01 and cx,0x1 | |||
aa: 74 32 je 0xde | |||
ac: 31 c0 xor ax,ax | |||
ae: 89 44 04 mov WORD PTR [si+0x4],ax | |||
b1: 40 inc ax | |||
b2: 88 44 ff mov BYTE PTR [si-0x1],al | |||
b5: 89 44 02 mov WORD PTR [si+0x2],ax | |||
b8: c7 04 10 00 mov WORD PTR [si],0x10 | |||
bc: 66 8b 1e 5c 7c mov ebx,DWORD PTR ds:0x7c5c | |||
c1: 66 89 5c 08 mov DWORD PTR [si+0x8],ebx | |||
c5: 66 8b 1e 60 7c mov ebx,DWORD PTR ds:0x7c60 | |||
ca: 66 89 5c 0c mov DWORD PTR [si+0xc],ebx | |||
ce: c7 44 06 00 70 mov WORD PTR [si+0x6],0x7000 | |||
d3: b4 42 mov ah,0x42 | |||
d5: cd 13 int 0x13 | |||
d7: 72 05 jb 0xde | |||
d9: bb 00 70 mov bx,0x7000 | |||
dc: eb 76 jmp 0x154 | |||
de: b4 08 mov ah,0x8 | |||
e0: cd 13 int 0x13 | |||
e2: 73 0d jae 0xf1 | |||
e4: 5a pop dx | |||
e5: 84 d2 test dl,dl | |||
e7: 0f 83 d8 00 jae 0x1c3 | |||
eb: be 8b 7d mov si,0x7d8b | |||
ee: e9 82 00 jmp 0x173 | |||
f1: 66 0f b6 c6 movzx eax,dh | |||
f5: 88 64 ff mov BYTE PTR [si-0x1],ah | |||
f8: 40 inc ax | |||
f9: 66 89 44 04 mov DWORD PTR [si+0x4],eax | |||
fd: 0f b6 d1 movzx dx,cl | |||
100: c1 e2 02 shl dx,0x2 | |||
103: 88 e8 mov al,ch | |||
105: 88 f4 mov ah,dh | |||
107: 40 inc ax | |||
108: 89 44 08 mov WORD PTR [si+0x8],ax | |||
10b: 0f b6 c2 movzx ax,dl | |||
10e: c0 e8 02 shr al,0x2 | |||
111: 66 89 04 mov DWORD PTR [si],eax | |||
114: 66 a1 60 7c mov eax,ds:0x7c60 | |||
118: 66 09 c0 or eax,eax | |||
11b: 75 4e jne 0x16b | |||
11d: 66 a1 5c 7c mov eax,ds:0x7c5c | |||
121: 66 31 d2 xor edx,edx | |||
124: 66 f7 34 div DWORD PTR [si] | |||
127: 88 d1 mov cl,dl | |||
129: 31 d2 xor dx,dx | |||
12b: 66 f7 74 04 div DWORD PTR [si+0x4] | |||
12f: 3b 44 08 cmp ax,WORD PTR [si+0x8] | |||
132: 7d 37 jge 0x16b | |||
134: fe c1 inc cl | |||
136: 88 c5 mov ch,al | |||
138: 30 c0 xor al,al | |||
13a: c1 e8 02 shr ax,0x2 | |||
13d: 08 c1 or cl,al | |||
13f: 88 d0 mov al,dl | |||
141: 5a pop dx | |||
142: 88 c6 mov dh,al | |||
144: bb 00 70 mov bx,0x7000 | |||
147: 8e c3 mov es,bx | |||
149: 31 db xor bx,bx | |||
14b: b8 01 02 mov ax,0x201 | |||
14e: cd 13 int 0x13 | |||
150: 72 1e jb 0x170 | |||
152: 8c c3 mov bx,es | |||
154: 60 pusha | |||
155: 1e push ds | |||
156: b9 00 01 mov cx,0x100 | |||
159: 8e db mov ds,bx | |||
15b: 31 f6 xor si,si | |||
15d: bf 00 80 mov di,0x8000 | |||
160: 8e c6 mov es,si | |||
162: fc cld | |||
163: f3 a5 rep movs WORD PTR es:[di],WORD PTR ds:[si] | |||
165: 1f pop ds | |||
166: 61 popa | |||
167: ff 26 5a 7c jmp WORD PTR ds:0x7c5a | |||
16b: be 86 7d mov si,0x7d86 | |||
16e: eb 03 jmp 0x173 | |||
170: be 95 7d mov si,0x7d95 | |||
173: e8 34 00 call 0x1aa | |||
176: be 9a 7d mov si,0x7d9a | |||
179: e8 2e 00 call 0x1aa | |||
17c: cd 18 int 0x18 | |||
17e: eb fe jmp 0x17e | |||
180: 47 inc di | |||
181: 52 push dx | |||
182: 55 push bp | |||
183: 42 inc dx | |||
184: 20 00 and BYTE PTR [bx+si],al | |||
186: 47 inc di | |||
187: 65 6f outs dx,WORD PTR gs:[si] | |||
189: 6d ins WORD PTR es:[di],dx | |||
18a: 00 48 61 add BYTE PTR [bx+si+0x61],cl | |||
18d: 72 64 jb 0x1f3 | |||
18f: 20 44 69 and BYTE PTR [si+0x69],al | |||
192: 73 6b jae 0x1ff | |||
194: 00 52 65 add BYTE PTR [bp+si+0x65],dl | |||
197: 61 popa | |||
198: 64 00 20 add BYTE PTR fs:[bx+si],ah | |||
19b: 45 inc bp | |||
19c: 72 72 jb 0x210 | |||
19e: 6f outs dx,WORD PTR ds:[si] | |||
19f: 72 0d jb 0x1ae | |||
1a1: 0a 00 or al,BYTE PTR [bx+si] | |||
1a3: bb 01 00 mov bx,0x1 | |||
1a6: b4 0e mov ah,0xe | |||
1a8: cd 10 int 0x10 | |||
1aa: ac lods al,BYTE PTR ds:[si] | |||
1ab: 3c 00 cmp al,0x0 | |||
1ad: 75 f4 jne 0x1a3 | |||
1af: c3 ret | |||
1b0: 00 00 add BYTE PTR [bx+si],al | |||
1b2: 00 00 add BYTE PTR [bx+si],al | |||
1b4: 00 00 add BYTE PTR [bx+si],al | |||
1b6: 00 00 add BYTE PTR [bx+si],al | |||
1b8: 6c ins BYTE PTR es:[di],dx | |||
1b9: 0f d1 b6 00 00 psrlw mm6,QWORD PTR [bp+0x0] | |||
1be: 00 20 add BYTE PTR [bx+si],ah | |||
1c0: 22 00 and al,BYTE PTR [bx+si] | |||
1c2: 83 fe ff cmp si,0xffff | |||
1c5: ff 01 inc WORD PTR [bx+di] | |||
1c7: 08 00 or BYTE PTR [bx+si],al | |||
1c9: 00 74 54 add BYTE PTR [si+0x54],dh | |||
1cc: 3d 39 00 cmp ax,0x39 | |||
1cf: fe (bad) | |||
1d0: ff (bad) | |||
1d1: ff 82 fe ff inc WORD PTR [bp+si-0x2] | |||
1d5: ff 75 5c push WORD PTR [di+0x5c] | |||
1d8: 3d 39 cc cmp ax,0xcc39 | |||
1db: ef out dx,ax | |||
1dc: fa cli | |||
1dd: 00 00 add BYTE PTR [bx+si],al | |||
1df: 00 00 add BYTE PTR [bx+si],al | |||
1e1: 00 00 add BYTE PTR [bx+si],al | |||
1e3: 00 00 add BYTE PTR [bx+si],al | |||
1e5: 00 00 add BYTE PTR [bx+si],al | |||
1e7: 00 00 add BYTE PTR [bx+si],al | |||
1e9: 00 00 add BYTE PTR [bx+si],al | |||
1eb: 00 00 add BYTE PTR [bx+si],al | |||
1ed: 00 00 add BYTE PTR [bx+si],al | |||
1ef: 00 00 add BYTE PTR [bx+si],al | |||
1f1: 00 00 add BYTE PTR [bx+si],al | |||
1f3: 00 00 add BYTE PTR [bx+si],al | |||
1f5: 00 00 add BYTE PTR [bx+si],al | |||
1f7: 00 00 add BYTE PTR [bx+si],al | |||
1f9: 00 00 add BYTE PTR [bx+si],al | |||
1fb: 00 00 add BYTE PTR [bx+si],al | |||
1fd: 00 55 aa add BYTE PTR [di-0x56],dl |
@ -0,0 +1,493 @@ | |||
WTF_Folmer_FuckedBootSector.bin: file format binary | |||
Disassembly of section .data: | |||
00000000 <.data>: | |||
0: e9 cb 01 jmp 0x1ce | |||
3: ff (bad) | |||
4: ff (bad) | |||
5: ff (bad) | |||
6: ff (bad) | |||
7: ff (bad) | |||
8: ff (bad) | |||
9: ff (bad) | |||
a: ff (bad) | |||
b: ff (bad) | |||
c: ff (bad) | |||
d: ff (bad) | |||
e: ff (bad) | |||
f: ff (bad) | |||
10: ff (bad) | |||
11: ff (bad) | |||
12: ff (bad) | |||
13: ff (bad) | |||
14: ff (bad) | |||
15: ff (bad) | |||
16: ff (bad) | |||
17: ff (bad) | |||
18: ff (bad) | |||
19: ff (bad) | |||
1a: ff (bad) | |||
1b: ff 00 inc WORD PTR [bx+si] | |||
1d: 00 00 add BYTE PTR [bx+si],al | |||
1f: 00 ff add bh,bh | |||
21: ff (bad) | |||
22: ff (bad) | |||
23: ff 00 inc WORD PTR [bx+si] | |||
25: ff (bad) | |||
26: ff (bad) | |||
27: ff (bad) | |||
28: ff (bad) | |||
29: ff (bad) | |||
2a: ff (bad) | |||
2b: ff (bad) | |||
2c: ff (bad) | |||
2d: ff (bad) | |||
2e: ff (bad) | |||
2f: ff (bad) | |||
30: ff (bad) | |||
31: ff (bad) | |||
32: ff (bad) | |||
33: ff (bad) | |||
34: ff (bad) | |||
35: ff (bad) | |||
36: ff (bad) | |||
37: ff (bad) | |||
38: ff (bad) | |||
39: ff (bad) | |||
3a: ff (bad) | |||
3b: ff (bad) | |||
3c: ff (bad) | |||
3d: ff (bad) | |||
3e: ff (bad) | |||
3f: ff (bad) | |||
40: ff (bad) | |||
41: ff (bad) | |||
42: ff (bad) | |||
43: ff (bad) | |||
44: ff (bad) | |||
45: ff (bad) | |||
46: ff (bad) | |||
47: ff (bad) | |||
48: ff (bad) | |||
49: ff (bad) | |||
4a: ff (bad) | |||
4b: ff (bad) | |||
4c: ff (bad) | |||
4d: ff (bad) | |||
4e: ff (bad) | |||
4f: ff (bad) | |||
50: ff (bad) | |||
51: ff (bad) | |||
52: ff (bad) | |||
53: ff (bad) | |||
54: ff (bad) | |||
55: ff (bad) | |||
56: ff (bad) | |||
57: ff (bad) | |||
58: ff (bad) | |||
59: ff (bad) | |||
5a: ff (bad) | |||
5b: ff (bad) | |||
5c: ff (bad) | |||
5d: ff (bad) | |||
5e: ff (bad) | |||
5f: ff (bad) | |||
60: ff (bad) | |||
61: ff (bad) | |||
62: ff (bad) | |||
63: ff (bad) | |||
64: ff (bad) | |||
65: ff (bad) | |||
66: ff (bad) | |||
67: ff (bad) | |||
68: ff (bad) | |||
69: ff (bad) | |||
6a: ff (bad) | |||
6b: ff (bad) | |||
6c: ff (bad) | |||
6d: ff (bad) | |||
6e: ff (bad) | |||
6f: ff (bad) | |||
70: ff (bad) | |||
71: ff (bad) | |||
72: ff (bad) | |||
73: ff (bad) | |||
74: ff (bad) | |||
75: ff (bad) | |||
76: ff (bad) | |||
77: ff (bad) | |||
78: ff (bad) | |||
79: ff (bad) | |||
7a: ff (bad) | |||
7b: ff (bad) | |||
7c: ff (bad) | |||
7d: ff (bad) | |||
7e: ff (bad) | |||
7f: ff (bad) | |||
80: ff (bad) | |||
81: ff (bad) | |||
82: ff (bad) | |||
83: ff (bad) | |||
84: ff (bad) | |||
85: ff (bad) | |||
86: ff (bad) | |||
87: ff (bad) | |||
88: ff (bad) | |||
89: ff (bad) | |||
8a: ff (bad) | |||
8b: ff (bad) | |||
8c: ff (bad) | |||
8d: ff (bad) | |||
8e: ff (bad) | |||
8f: ff (bad) | |||
90: ff (bad) | |||
91: ff (bad) | |||
92: ff (bad) | |||
93: ff (bad) | |||
94: ff (bad) | |||
95: ff (bad) | |||
96: ff (bad) | |||
97: ff (bad) | |||
98: ff (bad) | |||
99: ff (bad) | |||
9a: ff (bad) | |||
9b: ff (bad) | |||
9c: ff (bad) | |||
9d: ff (bad) | |||
9e: ff (bad) | |||
9f: ff (bad) | |||
a0: ff (bad) | |||
a1: ff (bad) | |||
a2: ff (bad) | |||
a3: ff (bad) | |||
a4: ff (bad) | |||
a5: ff (bad) | |||
a6: ff (bad) | |||
a7: ff (bad) | |||
a8: ff (bad) | |||
a9: ff (bad) | |||
aa: ff (bad) | |||
ab: ff (bad) | |||
ac: ff (bad) | |||
ad: ff (bad) | |||
ae: ff (bad) | |||
af: ff (bad) | |||
b0: ff (bad) | |||
b1: ff (bad) | |||
b2: ff (bad) | |||
b3: ff (bad) | |||
b4: ff (bad) | |||
b5: ff (bad) | |||
b6: ff (bad) | |||
b7: ff (bad) | |||
b8: ff (bad) | |||
b9: ff (bad) | |||
ba: ff (bad) | |||
bb: ff (bad) | |||
bc: ff (bad) | |||
bd: ff (bad) | |||
be: ff (bad) | |||
bf: ff (bad) | |||
c0: ff (bad) | |||
c1: ff (bad) | |||
c2: ff (bad) | |||
c3: ff (bad) | |||
c4: ff (bad) | |||
c5: ff (bad) | |||
c6: ff (bad) | |||
c7: ff (bad) | |||
c8: ff (bad) | |||
c9: ff (bad) | |||
ca: ff (bad) | |||
cb: ff (bad) | |||
cc: ff (bad) | |||
cd: ff (bad) | |||
ce: ff (bad) | |||
cf: ff (bad) | |||
d0: ff (bad) | |||
d1: ff (bad) | |||
d2: ff (bad) | |||
d3: ff (bad) | |||
d4: ff (bad) | |||
d5: ff (bad) | |||
d6: ff (bad) | |||
d7: ff (bad) | |||
d8: ff (bad) | |||
d9: ff (bad) | |||
da: ff (bad) | |||
db: ff (bad) | |||
dc: ff (bad) | |||
dd: ff (bad) | |||
de: ff (bad) | |||
df: ff (bad) | |||
e0: ff (bad) | |||
e1: ff (bad) | |||
e2: ff (bad) | |||
e3: ff (bad) | |||
e4: ff (bad) | |||
e5: ff (bad) | |||
e6: ff (bad) | |||
e7: ff (bad) | |||
e8: ff (bad) | |||
e9: ff (bad) | |||
ea: ff (bad) | |||
eb: ff (bad) | |||
ec: ff (bad) | |||
ed: ff (bad) | |||
ee: ff (bad) | |||
ef: ff (bad) | |||
f0: ff (bad) | |||
f1: ff (bad) | |||
f2: ff (bad) | |||
f3: ff (bad) | |||
f4: ff (bad) | |||
f5: ff (bad) | |||
f6: ff (bad) | |||
f7: ff (bad) | |||
f8: ff (bad) | |||
f9: ff (bad) | |||
fa: ff (bad) | |||
fb: ff (bad) | |||
fc: ff (bad) | |||
fd: ff (bad) | |||
fe: ff (bad) | |||
ff: ff (bad) | |||
100: ff (bad) | |||
101: ff (bad) | |||
102: ff (bad) | |||
103: ff (bad) | |||
104: ff (bad) | |||
105: ff (bad) | |||
106: ff (bad) | |||
107: ff (bad) | |||
108: ff (bad) | |||
109: ff (bad) | |||
10a: ff (bad) | |||
10b: ff (bad) | |||
10c: ff (bad) | |||
10d: ff (bad) | |||
10e: ff (bad) | |||
10f: ff (bad) | |||
110: ff (bad) | |||
111: ff (bad) | |||
112: ff (bad) | |||
113: ff (bad) | |||
114: ff (bad) | |||
115: ff (bad) | |||
116: ff (bad) | |||
117: ff (bad) | |||
118: ff (bad) | |||
119: ff (bad) | |||
11a: ff (bad) | |||
11b: ff (bad) | |||
11c: ff (bad) | |||
11d: ff (bad) | |||
11e: ff (bad) | |||
11f: ff (bad) | |||
120: ff (bad) | |||
121: ff (bad) | |||
122: ff (bad) | |||
123: ff (bad) | |||
124: ff (bad) | |||
125: ff (bad) | |||
126: ff (bad) | |||
127: ff (bad) | |||
128: ff (bad) | |||
129: ff (bad) | |||
12a: ff (bad) | |||
12b: ff (bad) | |||
12c: ff (bad) | |||
12d: ff (bad) | |||
12e: ff (bad) | |||
12f: ff (bad) | |||
130: ff (bad) | |||
131: ff (bad) | |||
132: ff (bad) | |||
133: ff (bad) | |||
134: ff (bad) | |||
135: ff (bad) | |||
136: ff (bad) | |||
137: ff (bad) | |||
138: ff (bad) | |||
139: ff (bad) | |||
13a: ff (bad) | |||
13b: ff (bad) | |||
13c: ff (bad) | |||
13d: ff (bad) | |||
13e: ff (bad) | |||
13f: ff (bad) | |||
140: ff (bad) | |||
141: ff (bad) | |||
142: ff (bad) | |||
143: ff (bad) | |||
144: ff (bad) | |||
145: ff (bad) | |||
146: ff (bad) | |||
147: ff (bad) | |||
148: ff (bad) | |||
149: ff (bad) | |||
14a: ff (bad) | |||
14b: ff (bad) | |||
14c: ff (bad) | |||
14d: ff (bad) | |||
14e: ff (bad) | |||
14f: ff (bad) | |||
150: ff (bad) | |||
151: ff (bad) | |||
152: ff (bad) | |||
153: ff (bad) | |||
154: ff (bad) | |||
155: ff (bad) | |||
156: ff (bad) | |||
157: ff (bad) | |||
158: ff (bad) | |||
159: ff (bad) | |||
15a: ff (bad) | |||
15b: ff (bad) | |||
15c: ff (bad) | |||
15d: ff (bad) | |||
15e: ff (bad) | |||
15f: ff (bad) | |||
160: ff (bad) | |||
161: ff (bad) | |||
162: ff (bad) | |||
163: ff (bad) | |||
164: ff (bad) | |||
165: ff (bad) | |||
166: ff (bad) | |||
167: ff (bad) | |||
168: ff (bad) | |||
169: ff (bad) | |||
16a: ff (bad) | |||
16b: ff (bad) | |||
16c: ff (bad) | |||
16d: ff (bad) | |||
16e: ff (bad) | |||
16f: ff (bad) | |||
170: ff (bad) | |||
171: ff (bad) | |||
172: ff (bad) | |||
173: ff (bad) | |||
174: ff (bad) | |||
175: ff (bad) | |||
176: ff (bad) | |||
177: ff (bad) | |||
178: ff (bad) | |||
179: ff (bad) | |||
17a: ff (bad) | |||
17b: ff (bad) | |||
17c: ff (bad) | |||
17d: ff (bad) | |||
17e: ff (bad) | |||
17f: ff (bad) | |||
180: ff (bad) | |||
181: ff (bad) | |||
182: ff (bad) | |||
183: ff (bad) | |||
184: ff (bad) | |||
185: ff (bad) | |||
186: ff (bad) | |||
187: ff (bad) | |||
188: ff (bad) | |||
189: ff (bad) | |||
18a: ff (bad) | |||
18b: ff (bad) | |||
18c: ff (bad) | |||
18d: ff (bad) | |||
18e: ff (bad) | |||
18f: ff (bad) | |||
190: ff (bad) | |||
191: ff (bad) | |||
192: ff (bad) | |||
193: ff (bad) | |||
194: ff (bad) | |||
195: ff (bad) | |||
196: ff (bad) | |||
197: ff (bad) | |||
198: ff (bad) | |||
199: ff (bad) | |||
19a: ff (bad) | |||
19b: ff (bad) | |||
19c: ff (bad) | |||
19d: ff (bad) | |||
19e: ff (bad) | |||
19f: ff (bad) | |||
1a0: ff (bad) | |||
1a1: ff (bad) | |||
1a2: ff (bad) | |||
1a3: ff (bad) | |||
1a4: ff (bad) | |||
1a5: ff (bad) | |||
1a6: ff (bad) | |||
1a7: ff (bad) | |||
1a8: ff (bad) | |||
1a9: ff (bad) | |||
1aa: ff (bad) | |||
1ab: ff (bad) | |||
1ac: ff (bad) | |||
1ad: ff (bad) | |||
1ae: ff (bad) | |||
1af: ff (bad) | |||
1b0: ff (bad) | |||
1b1: ff (bad) | |||
1b2: ff (bad) | |||
1b3: ff (bad) | |||
1b4: ff (bad) | |||
1b5: ff (bad) | |||
1b6: ff (bad) | |||
1b7: ff (bad) | |||
1b8: ff (bad) | |||
1b9: ff (bad) | |||
1ba: ff (bad) | |||
1bb: ff (bad) | |||
1bc: ff (bad) | |||
1bd: ff (bad) | |||
1be: ff (bad) | |||
1bf: ff (bad) | |||
1c0: ff (bad) | |||
1c1: ff (bad) | |||
1c2: ff (bad) | |||
1c3: ff (bad) | |||
1c4: ff (bad) | |||
1c5: ff (bad) | |||
1c6: ff (bad) | |||
1c7: ff (bad) | |||
1c8: ff (bad) | |||
1c9: ff (bad) | |||
1ca: ff (bad) | |||
1cb: ff (bad) | |||
1cc: ff (bad) | |||
1cd: ff 31 push WORD PTR [bx+di] | |||
1cf: c0 8e c0 bb 00 ror BYTE PTR [bp-0x4440],0x0 | |||
1d4: 7c b8 jl 0x18e | |||
1d6: 01 03 add WORD PTR [bp+di],ax | |||
1d8: b9 02 00 mov cx,0x2 | |||
1db: 30 f6 xor dh,dh | |||
1dd: cd 13 int 0x13 | |||
1df: b9 10 00 mov cx,0x10 | |||
1e2: 93 xchg bx,ax | |||
1e3: b8 18 0e mov ax,0xe18 | |||
1e6: d1 e3 shl bx,1 | |||
1e8: d0 d0 rcl al,1 | |||
1ea: cd 10 int 0x10 | |||
1ec: e2 f5 loop 0x1e3 | |||
1ee: fa cli | |||
1ef: f4 hlt | |||
1f0: eb fc jmp 0x1ee | |||
1f2: 90 nop | |||
1f3: 90 nop | |||
1f4: 90 nop | |||
1f5: 90 nop | |||
1f6: 90 nop | |||
1f7: 90 nop | |||
1f8: 90 nop | |||
1f9: 90 nop | |||
1fa: 90 nop | |||
1fb: 90 nop | |||
1fc: 90 nop | |||
1fd: 90 nop | |||
1fe: 55 push bp | |||
1ff: aa stos BYTE PTR es:[di],al |
@ -0,0 +1,781 @@ | |||
(Table 00010) | |||
Values for video mode: | |||
text/ text pixel pixel colors disply scrn system | |||
grph resol box resolution pages addr | |||
00h = T 40x25 8x8 320x200 16gray 8 B800 CGA,PCjr,Tandy | |||
= T 40x25 8x14 320x350 16gray 8 B800 EGA | |||
= T 40x25 8x16 320x400 16 8 B800 MCGA | |||
= T 40x25 9x16 360x400 16 8 B800 VGA | |||
01h = T 40x25 8x8 320x200 16 8 B800 CGA,PCjr,Tandy | |||
= T 40x25 8x14 320x350 16 8 B800 EGA | |||
= T 40x25 8x16 320x400 16 8 B800 MCGA | |||
= T 40x25 9x16 360x400 16 8 B800 VGA | |||
02h = T 80x25 8x8 640x200 16gray 4 B800 CGA,PCjr,Tandy | |||
= T 80x25 8x14 640x350 16gray 8 B800 EGA | |||
= T 80x25 8x16 640x400 16 8 B800 MCGA | |||
= T 80x25 9x16 720x400 16 8 B800 VGA | |||
03h = T 80x25 8x8 640x200 16 4 B800 CGA,PCjr,Tandy | |||
= T 80x25 8x14 640x350 16/64 8 B800 EGA | |||
= T 80x25 8x16 640x400 16 8 B800 MCGA | |||
= T 80x25 9x16 720x400 16 8 B800 VGA | |||
= T 80x43 8x8 640x350 16 4 B800 EGA,VGA [17] | |||
= T 80x50 8x8 640x400 16 4 B800 VGA [17] | |||
04h = G 40x25 8x8 320x200 4 . B800 CGA,PCjr,EGA,MCGA,VGA | |||
05h = G 40x25 8x8 320x200 4gray . B800 CGA,PCjr,EGA | |||
= G 40x25 8x8 320x200 4 . B800 MCGA,VGA | |||
06h = G 80x25 8x8 640x200 2 . B800 CGA,PCjr,EGA,MCGA,VGA | |||
= G 80x25 . . mono . B000 HERCULES.COM on HGC [14] | |||
07h = T 80x25 9x14 720x350 mono var B000 MDA,Hercules,EGA | |||
= T 80x25 9x16 720x400 mono . B000 VGA | |||
08h = T 132x25 8x8 1056x200 16 . B800 ATI EGA/VGA Wonder [2] | |||
= T 132x25 8x8 1056x200 mono . B000 ATI EGA/VGA Wonder [2] | |||
= G 20x25 8x8 160x200 16 . . PCjr, Tandy 1000 | |||
= G 80x25 8x16 640x400 color . . Tandy 2000 | |||
= G 90x43 8x8 720x348 mono . B000 Hercules + MSHERC.COM | |||
= G 90x45 8x8 720x360 mono . B000 Hercules + HERKULES [11] | |||
= G 90x29 8x12 720x348 mono . . Hercules + HERCBIOS [15] | |||
09h = G 40x25 8x8 320x200 16 . . PCjr, Tandy 1000 | |||
= G 80x25 8x16 640x400 mono . . Tandy 2000 | |||
= G 90x43 8x8 720x348 mono . . Hercules + HERCBIOS [15] | |||
0Ah = G 80x25 8x8 640x200 4 . . PCjr, Tandy 1000 | |||
0Bh = reserved (EGA BIOS internal use) | |||
= G 80x25 8x8 640x200 16 . . Tandy 1000 SL/TL [13] | |||
0Ch = reserved (EGA BIOS internal use) | |||
0Dh = G 40x25 8x8 320x200 16 8 A000 EGA,VGA | |||
0Eh = G 80x25 8x8 640x200 16 4 A000 EGA,VGA | |||
0Fh = G 80x25 8x14 640x350 mono 2 A000 EGA,VGA | |||
10h = G 80x25 8x14 640x350 4 2 A000 64k EGA | |||
= G . . 640x350 16 . A000 256k EGA,VGA | |||
11h = G 80x30 8x16 640x480 mono . A000 VGA,MCGA,ATI EGA,ATI VIP | |||
12h = G 80x30 8x16 640x480 16/256K . A000 VGA,ATI VIP | |||
= G 80x30 8x16 640x480 16/64 . A000 ATI EGA Wonder | |||
= G . . 640x480 16 . . UltraVision+256K EGA | |||
13h = G 40x25 8x8 320x200 256/256K . A000 VGA,MCGA,ATI VIP | |||
14h = T 132x25 Nx16 . 16 . B800 XGA, IBM Enhanced VGA [3] | |||
= T 132x25 8x16 1056x400 16/256K . . Cirrus CL-GD5420/5422/5426 | |||
= G 80x25 8x8 640x200 . . . Lava Chrome II EGA | |||
= G . . 640x400 16 . . Tecmar VGA/AD | |||
15h = G 80x25 8x14 640x350 . . . Lava Chrome II EGA | |||
16h = G 80x25 8x14 640x350 . . . Lava Chrome II EGA | |||
= G . . 800x600 16 . . Tecmar VGA/AD | |||
17h = T 132x25 . . . . . Tecmar VGA/AD | |||
= T 80x43 8x8 640x348 16 4 B800 Tseng ET4000 BIOS [10] | |||
= G 80x34 8x14 640x480 . . . Lava Chrome II EGA | |||
18h = T 80x30 9x16 720x480 16 1 A000 Realtek RTVGA [12] | |||
= T 132x25 . . mono . B000 Cirrus 5320 chipset | |||
= T 132x44 8x8 1056x352 mono . B000 Tseng Labs EVA | |||
= T 132x44 9x8 1188x352 4gray 2 B000 Tseng ET3000 chipset | |||
= T 132x44 8x8 1056x352 16/256 2 B000 Tseng ET4000 chipset | |||
= G 80x34 8x14 640x480 . . . Lava Chrome II EGA | |||
= G 1024x768 16 . . Tecmar VGA/AD | |||
19h = T 80x43 9x11 720x473 16 1 A000 Realtek RTVGA [12] | |||
= T 132x25 8x14 1056x350 mono . B000 Tseng Labs EVA | |||
= T 132x25 9x14 1188x350 4gray 4 B000 Tseng ET3000 chipset | |||
= T 132x25 8x14 1056x350 16/256 4 B000 Tseng ET4000 chipset | |||
= T 132x34 . . mono . B000 Cirrus 5320 chipset | |||
1Ah = T 80x60 9x8 720x480 16 1 A000 Realtek RTVGA [12] | |||
= T 132x28 8x13 1056x364 mono . B000 Tseng Labs EVA | |||
= T 132x28 9x13 1188x364 4gray 4 B000 Tseng ET3000 chipset | |||
= T 132x28 8x13 1056x364 16/256 4 B000 Tseng ET4000 chipset | |||
= T 132x44 . . mono . B000 Cirrus 5320 chipset | |||
= G . . 640x350 256 . . Tecmar VGA/AD | |||
1Bh = T 132x25 9x14 1188x350 16 1 A000 Realtek RTVGA [12] | |||
= G . . 640x400 256 . . Tecmar VGA/AD | |||
1Ch = T 132x25 . . . . . Cirrus 5320 chipset | |||
= T 132x30 9x16 1188x480 16 1 A000 Realtek RTVGA [12] | |||
= G . . 640x480 256 . . Tecmar VGA/AD | |||
1Dh = T 132x43 . . . . . Cirrus 5320 chipset | |||
= T 132x43 9x11 1188x473 16 1 A000 Realtek RTVGA [12] | |||
= G . . 800x600 256 . . Tecmar VGA/AD | |||
1Eh = T 132x44 . . . . . Cirrus 5320 chipset | |||
= T 132x60 9x8 1188x480 16 1 A000 Realtek RTVGA [12] | |||
1Fh = G 100x75 8x8 800x600 16 1 A000 Realtek RTVGA | |||
20h = T 132x25 . . 16 . . Avance Logic AL2101 | |||
= G 40x16 . 240x128 mono . B000 HP 95LX/100LX/200LX | |||
= G 80x30 8x16 640x480 16 . . C&T 64310/65530 BIOS | |||
= G 120x45 8x16 960x720 16 1 A000 Realtek RTVGA | |||
21h = T 80x25 . . mono . B000 HP 200LX | |||
= T 132x30 . . 16 . . Avance Logic AL2101 | |||
= T 132x44 9x9 1188x396 16/256K . B800 WD90C | |||
= T 132x44 9x9 1188x396 16 . B800 Diamond Speedstar 24X | |||
= T 132x60 . . 16 2 B800 Tseng ET4000 chipset [10] | |||
= G 80x43 8x8 720x348 mono . B000 DESQview 2.x+Hercules [4] | |||
= G 128x48 8x16 1024x768 16 1 A000 Realtek RTVGA [12] | |||
22h = T 132x43 . . . . . Allstar Peacock (VGA) | |||
= T 132x43 . . 16 . . Avance Logic AL2101 | |||
= T 132x44 8x8 1056x352 . . B800 Tseng Labs EVA | |||
= T 132x44 9x8 1188x352 16/256K 2 B800 Tseng ET3000 chipset | |||
= T 132x44 8x8 1056x352 16/256K 2 B800 Tseng ET4000 chipset | |||
= T 132x44 8x8 1056x352 . . . Ahead Systems EGA2001 | |||
= T 132x44 8x8 1056x352 16 2 B800 Ahead B | |||
= T 132x44 8x9 1056x398 16 . . STB Lightspeed ET4000/W32P | |||
= T 132x44 . . 16 . . Orchid Prodesigner VGA | |||
= G 80x43 8x8 720x348 mono . B800 DESQview 2.x+Hercules [4] | |||
= G 96x64 8x16 768x1024 16 1 A000 Realtek RTVGA | |||
= G 100x37 8x16 800x600 16 . . C&T 64310/65530 BIOS | |||
23h = T 132x25 6x14 792x350 . . B800 Tseng Labs EVA | |||
= T 132x25 9x14 1188x350 16/256K 4 B800 Tseng ET3000 chipset | |||
= T 132x25 8x14 1056x350 16/256 4 B800 Tseng ET4000 chipset | |||
= T 132x25 8x14 1056x350 . . . Ahead Systems EGA2001 | |||
= T 132x25 8x14 1056x350 16 4 B800 Ahead B | |||
= T 132x25 8x8 1056x200 16 . B800 ATI EGA Wonder,ATI VIP | |||
= T 132x25 . . . . . Cirrus 5320 chipset | |||
= T 132x28 . . . . . Allstar Peacock (VGA) | |||
= T 132x28 . . 16 . . Orchid Prodesigner VGA | |||
= T 132x60 . . 16 . . Avance Logic AL2101 | |||
= G 128x48 8x16 1024x768 4 1 A000 Realtek RTVGA | |||
24h = T 80x30 . . 16 . . Avance Logic AL2101 | |||
= T 132x25 . . . . . Allstar Peacock (VGA) | |||
= T 132x25 . . 16 . . Orchid Prodesigner VGA | |||
= T 132x28 6x13 792x364 . . B800 Tseng Labs EVA | |||
= T 132x28 9x13 1188x364 16/256K 4 B800 Tseng ET3000 chipset | |||
= T 132x28 8x12 1056x336 16 1 B800 Ahead B | |||
= T 132x28 8x13 1056x364 16/256K 4 B800 Tseng ET4000 chipset | |||
= T 132x28 8x14 1056x392 16 . . STB Lightspeed ET4000/W32P | |||
= T 132x28 . . . . . Cirrus 5320 chipset | |||
= G 64x32 8x16 512x512 256 1 A000 Realtek RTVGA | |||
= G 128x48 8x16 1024x768 16 . . C&T 64310/65530 BIOS | |||
25h = T 80x43 . . 16 . . Avance Logic AL2101 | |||
= G 80x60 8x8 640x480 . . A000 Tseng Labs EVA | |||
= G 80x60 8x8 640x480 16/256K 1 A000 Tseng ET3000/4000 chipset | |||
= G . . 640x480 16 . . VEGA VGA | |||
= G 80x60 8x8 640x480 16 . A000 Orchid Prodesigner VGA | |||
= G 80x60 8x8 640x480 16 1 A000 Ahead B (same as 26h) | |||
= G . . 640x480 16 . . NEC GB-1 | |||
= G . . 640x480 16 . . Cirrus 5320 chipset | |||
= G . . 640x400 256 . . Realtek RTVGA | |||
26h = T 80x60 8x8 640x480 . . . Tseng Labs EVA | |||
= T 80x60 8x8 640x480 16/256K 3 B800 Tseng ET3000/4000 chipset | |||
= T 80x60 . . . . . Allstar Peacock (VGA) | |||
= T 80x60 . . 16 . . Orchid ProDesigner VGA | |||
= T 80x60 . . 16 . . Avance Logic AL2101 | |||
= G 80x60 8x8 640x480 . . . Ahead Systems EGA2001 | |||
= G 80x60 8x8 640x480 16 1 A000 Ahead B (same as 25h) | |||
= G . . 640x480 256 . . Realtek RTVGA | |||
27h = T 132x25 8x8 1056x200 mono . B000 ATI EGA Wonder,ATI VIP | |||
= G . . 720x512 16 . . VEGA VGA | |||
= G . . 720x512 16 . . Genoa | |||
= G 100x75 8x8 800x600 256 1 A000 Realtek RTVGA [12] | |||
= G . . 960x720 16 . . Avance Logic AL2101 | |||
28h = T ???x??? . . . . . VEGA VGA | |||
= G . . 512x512 256 . . Avance Logic AL2101 | |||
= G . . 1024x768 256 . . Realtek RTVGA (1meg) | |||
= G 160x64 8x16 1280x1024 16 . . Chips&Technologies 64310 [1] | |||
29h = G . . 640x400 256 . . Avance Logic AL2101 | |||
= G . . 800x600 16 . . VEGA VGA | |||
= G 100x37 8x16 800x600 16 . A000 Orchid | |||
= G . . 800x600 16 . A000 STB,Genoa,Sigma | |||
= G . . 800x600 16 . . Allstar Peacock (VGA) | |||
= G 100x37 8x16 800x600 16/256K 1 A000 Tseng ET3000/4000 chipset | |||
= G . . 800x600 ??? . . EIZO MDB10 | |||
= G . . 800x600 16 . . Cirrus 5320 chipset | |||
= G NA . 800x600 16 . . Compaq QVision 1024/1280 | |||
= G . . 1024x1024 256 . . Realtek RTVGA BIOS v3.C10 | |||
2Ah = T 100x40 . . . . . Allstar Peacock (VGA) | |||
= T 100x40 8x16 800x640 16 . . Orchid Prodesigner VGA | |||
= T 100x40 8x15 800x600 16/256K 4 B800 Tseng ET3000/4000 chipset | |||
= T 100x40 8x15 800x600 16 . . STB Lightspeed ET4000/W32P | |||
= G . . 640x480 256 . . Avance Logic AL2101 | |||
= G . . 1280x1024 16 . . Realtek RTVGA | |||
2Bh = G . . 800x600 16 . . Avance Logic AL2101 | |||
2Ch = G . . 800x600 256 . . Avance Logic AL2101 | |||
2Dh = G . . 640x350 256 . . VEGA VGA | |||
= G . . 640x350 256/256K . A000 Orchid, Genoa, STB | |||
= G 80x25 8x14 640x350 256/256K 1 A000 Tseng ET3000/4000 chipset | |||
= G . . 640x350 256 . . Cirrus 5320 chipset | |||
= G 80x25 8x14 640x350 256 . . STB Lightspeed ET4000/W32P | |||
= G . . 768x1024 16 . . Avance Logic AL2101 | |||
2Eh = G . . 640x480 256 . . VEGA VGA | |||
= G 80x30 8x16 640x480 256/256K . A000 Orchid | |||
= G . . 640x480 256/256K . A000 STB,Genoa,Sigma | |||
= G 80x30 8x16 640x480 256/256K 1 A000 Tseng ET3000/4000 chipset | |||
= G . . 640x480 256/256K . . Compaq QVision 1024/1280 | |||
= G . . 768x1024 256 . . Avance Logic AL2101 | |||
2Fh = T 160x50 8x8 1280x400 16 4 B800 Ahead B (Wizard/3270) | |||
= G . . 720x512 256 . . VEGA VGA | |||
= G . . 720x512 256 . . Genoa | |||
= G 80x25 8x16 640x400 256/256K 1 A000 Tseng ET4000 chipset | |||
= G . . 1024x768 4 . . Avance Logic AL2101 | |||
30h = G 80x30 8x16 640x480 256 . . C&T 64310/65530 BIOS | |||
= G . . . . . B800 AT&T 6300 | |||
= G . . 720x350 2 . . 3270 PC | |||
= G . . 800x600 256 . . VEGA VGA | |||
= G 100x37 8x16 800x600 256/256K . A000 Orchid | |||
= G . . 800x600 256/256K . A000 STB,Genoa,Sigma | |||
= G . . 800x600 256 . . Cardinal | |||
= G 100x37 8x16 800x600 256/256K 1 A000 Tseng ET3000/4000 chipset | |||
= G . . 1024x768 16 . . Avance Logic AL2101 | |||
31h = G . . 1024x768 256 . . Avance Logic AL2101 | |||
32h = T 80x34 8x10 . 16 4 B800 Ahead B (Wizard/3270) | |||
= G . . 640x480 256 . . Compaq QVision 1024/1280 | |||
= G 100x37 8x16 800x600 256 . . C&T 64310/65530 BIOS | |||
33h = T 132x44 8x8 . 16 . B800 ATI EGA Wonder,ATI VIP | |||
= T 80x34 8x8 . 16 4 B800 Ahead B (Wizard/3270) | |||
34h = T 80x66 8x8 . 16 4 B800 Ahead B (Wizard/3270) | |||
= G . . 800x600 256 . . Compaq QVision 1024/1280 | |||
= G 128x48 8x16 1024x768 256 . . Chips&Technologies 64310 | |||
36h = G . . 960x720 16 . . VEGA VGA, STB | |||
= G . . 960x720 16 . A000 Tseng ET3000 only | |||
= G . . 1280x1024 16 . . Avance Logic AL2101 | |||
37h = T 132x44 8x8 . mono . B800 ATI EGA Wonder,ATI VIP | |||
= G . . 1024x768 16 . . VEGA VGA | |||
= G 128x48 8x16 1024x768 16 . A000 Orchid | |||
= G . . 1024x768 16 . A000 STB,Genoa,Sigma | |||
= G . . 1024x768 16 . . Definicon | |||
= G 128x48 8x16 1024x768 16 1 A000 Tseng ET3000/4000 chipset | |||
= G . . 1024x768 16 . . Compaq QVision 1024/1280 | |||
= G . . 1280x1024 256 . . Avance Logic AL2101 | |||
38h = G . . 1024x768 256 . . STB VGA/EM-16 Plus (1MB) | |||
= G 128x48 8x16 1024x768 256/256K 1 A000 Tseng ET4000 chipset | |||
= G . . 1024x768 256 . . Orchid ProDesigner II | |||
= G . . 1024x768 256 . . Compaq QVision 1024/1280 | |||
= G 160x64 8x16 1280x1024 256 . . Chips&Technologies 64310 [1] | |||
39h = G . . 1280x1024 16 . . Compaq QVision 1280 | |||
3Ah = G . . 1280x1024 256 . . Compaq QVision 1280 | |||
3Bh = G . . 512x480 256 . . Compaq QVision 1024/1280 | |||
3Ch = G . . 640x400 64K . . Compaq QVision 1024/1280 | |||
3Dh = G . . 1280x1024 16 . . Definicon | |||
= G 128x64 8x16 1280x1024 16 1 A000 Tseng ET4000 v3.00 [1,7] | |||
3Eh = G . . 1280x961 16 . . Definicon | |||
= G . . 640x480 64K . . Compaq QVision 1024/1280 | |||
3Fh = G . . 1280x1024 256 . . Hercules ??? (ET4000W32) | |||
= G . . 800x600 64K . . Compaq QVision 1024/1280 | |||
40h = T 80x43 . . . . . VEGA VGA, Tecmar VGA/AD | |||
= T 80x43 . . . . . Video7 V-RAM VGA | |||
= T 80x43 . . . . . Tatung VGA | |||
= T 100x30 . . 16 . . MORSE VGA | |||
= T 100x30 . . . . . Cirrus 510/520 chipset | |||
= T 80x25 . 720x350 mono . . Genoa SuperEGA BIOS 3.0+ | |||
= G . . 320x200 64K . . Avance Logic AL2101 | |||
= G 80x25 8x16 640x400 2 1 B800 AT&T 6300, AT&T VDC600 | |||
= G 80x25 8x16 640x400 2 1 B800 Olivetti Quaderno | |||
= G 80x25 8x16 640x400 2 1 B800 Compaq Portable | |||
= G 80x30 8x16 640x480 32K . . Chips&Technologies 64310 | |||
= G . . 1024x768 64K . . Compaq QVision 1280 | |||
41h = T 132x25 . . . . . VEGA VGA | |||
= T 132x25 . . . . . Tatung VGA | |||
= T 132x25 . . . . . Video7 V-RAM VGA | |||
= T 100x50 . . 16 . . MORSE VGA | |||
= T 100x50 . . . . . Cirrus 510/520 chipset | |||
= T 80x34 9x14 720x476 16/256K . B800 WD90C | |||
= T 80x34 9x14 . 16 . B800 Diamond Speedstar 24X | |||
= G . . 512x512 64K . . Avance Logic AL2101 | |||
= G . . 640x200 16 1 . AT&T 6300 | |||
= G 80x30 8x16 640x480 64K . . Chips&Technologies 64310 | |||
= G 80x25 . 720x348 mono . B000 Genoa SuperEGA BIOS 3.0+ | |||
42h = T 132x43 . . . . . VEGA VGA | |||
= T 132x43 . . . . . Tatung VGA | |||
= T 132x43 . . . . . Video7 V-RAM VGA | |||
= T 80x34 9x10 . 4 4 B800 Ahead B (Wizard/3270) | |||
= T 100x60 . . 16 . . MORSE VGA | |||
= T 100x60 . . . . . Cirrus 510/520 chipset | |||
= G 80x25 8x16 640x400 16 . . AT&T 6300, AT&T VDC600 | |||
= G . . 640x400 64K . . Avance Logic AL2101 | |||
= G 80x25 . 720x348 mono . B800 Genoa SuperEGA BIOS 3.0+ | |||
= G 100x37 8x16 800x600 32K . . Chips&Technologies 64310 | |||
43h = T 80x60 . . . . . VEGA VGA | |||
= T 80x60 . . . . . Tatung VGA | |||
= T 80x60 . . . . . Video7 V-RAM VGA | |||
= T 80x45 9x8 . 4 4 B800 Ahead B (Wizard/3270) | |||
= T 100x75 . . 16 . . MORSE VGA | |||
= T 80x29 . 720x348 mono . . Genoa SuperEGA BIOS 3.0+ | |||
= G . . 640x200 of 640x400 viewport AT&T 6300 (unsupported) | |||
= G . . 640x480 64K . . Avance Logic AL2101 | |||
= G 100x37 8x16 800x600 64K . . Chips&Technologies 64310 | |||
44h = disable VDC and DEB output . AT&T 6300 | |||
= T 100x60 . . . . . VEGA VGA | |||
= T 100x60 . . . . . Tatung VGA | |||
= T 100x60 . . . . . Video7 V-RAM VGA | |||
= T 80x32 . 720x352 mono . . Genoa SuperEGA BIOS 3.0+ | |||
= G . . 800x600 64K . . Avance Logic AL2101 | |||
45h = T 132x28 . . . . . Tatung VGA | |||
= T 132x28 . . . . . Video7 V-RAM VGA | |||
= T 80x44 . 720x352 mono . . Genoa SuperEGA BIOS 3.0+ | |||
46h = T 132x25 8x14 . mono . . Genoa 6400 | |||
= T 132x25 9x14 . mono . . Genoa SuperEGA BIOS 3.0+ | |||
= G 100x40 8x15 800x600 2 . . AT&T VDC600 | |||
47h = T 132x29 8x12 . mono . . Genoa 6400 | |||
= T 132x29 9x12 . mono . . Genoa SuperEGA BIOS 3.0+ | |||
= T 132x28 9x16 1188x448 16/256K . B800 WD90C | |||
= T 132x28 9x16 . 16 . B800 Diamond Speedstar 24X | |||
= G 100x37 8x16 800x600 16 . . AT&T VDC600 | |||
48h = T 132x32 8x12 . mono . . Genoa 6400 | |||
= T 132x32 9x11 . mono . . Genoa SuperEGA BIOS 3.0+ | |||
= G 80x50 8x8 640x400 2 . B800 AT&T 6300, AT&T VDC600 | |||
= G 80x50 8x8 640x400 2 . B800 Olivetti Quaderno | |||
49h = T 132x44 8x8 . mono . . Genoa 6400 | |||
= T 132x44 9x8 . mono . . Genoa SuperEGA BIOS 3.0+ | |||
= G 80x30 8x16 640x480 . . . Lava Chrome II EGA | |||
= G 80x30 8x16 640x480 . . A000 Diamond Stealth64 Video 2xx1 | |||
4Bh = G 100x37 8x16 800x600 . . A000 Diamond Stealth64 Video 2xx1 | |||
4Dh = T 120x25 . . . . . VEGA VGA | |||
= G . . 512x480 16M . . Compaq QVision 1024/1280 | |||
= G 128x48 8x16 1024x768 . . A000 Diamond Stealth64 Video 2xx1 | |||
4Eh = T 120x43 . . . . . VEGA VGA | |||
= T 80x60 8x8 . 16/256K . B800 Oak OTI-067/OTI-077 [8] | |||
= G . . 640x400 16M . . Compaq QVision 1024/1280 | |||
= G 144x54 8x16 1152x864 . . A000 Diamond Stealth64 Video 2xx1 | |||
4Fh = T 132x25 . . . . . VEGA VGA | |||
= T 132x60 . . . . . some Oak Tech VGA [8] | |||
= G . . 640x480 16M . . Compaq QVision 1280 | |||
50h = T 80x30 8x16 . 16/256K . B800 Trident TVGA 8800/8900 | |||
= T 80x34 . . . . . Lava Chrome II EGA | |||
= T 80x43 . . mono . . VEGA VGA | |||
= T 132x25 9x14 . mono . . Ahead Systems EGA2001 | |||
= T 132x25 9x14 . 4 4 B800 Ahead B | |||
= T 132x25 8x14 . 16 8 B800 OAK Technologies VGA-16 | |||
= T 132x25 8x14 . 16/256K . B800 Oak OTI-037/067/077 [8] | |||
= T 132x25 8x14 1056x350 16 8 B800 UM587 chipset | |||
= T 132x30 . . 16 . . MORSE VGA | |||
= T 132x30 . . . . . Cirrus 510/520 chipset | |||
= G 80x30 8x16 640x480 16 . . Paradise EGA-480 | |||
= G 80x30 8x16 640x480 16 . . NEL Electronics BIOS | |||
= G 80x30 8x16 640x480 16M . . Chips&Technologies 64310 | |||
= G . . 640x480 mono??? . . Taxan 565 EGA | |||
= G 40x25 8x8 320x200 . . . Genoa SuperEGA BIOS 3.0+ | |||
51h = T 80x30 8x16 . . . . Paradise EGA-480 | |||
= T 80x30 9x16 . . . . NEL Electronics BIOS | |||
= T 80x30 . . . . . Lava Chrome II EGA | |||
= T 80x43 8x11 . 16/256K . B800 Trident TVGA 8800/8900 | |||
= T 132x25 . . mono . . VEGA VGA | |||
= T 132x28 9x12 . 4 4 B800 Ahead B | |||
= T 132x43 8x8 . 16 5 B800 OAK Technologies VGA-16 | |||
= T 132x43 8x8 . 16/256K . B800 Oak OTI-037/067/077 | |||
= T 132x43 8x8 1056x344 16 5 B800 UM587 chipset | |||
= T 132x50 . . 16 . . MORSE VGA | |||
= T 132x50 . . . . . Cirrus 510/520 chipset | |||
= G 80x34 8x14 640x480 16 . . ATI EGA Wonder | |||
= G 80x25 8x8 640x200 . . . Genoa SuperEGA BIOS 3.0+ | |||
52h = T 80x60 . . . . . Lava Chrome II EGA | |||
= T 80x60 8x8 . 16/256K . B800 Trident TVGA 8800/8900 | |||
= T 132x43 . . mono . . VEGA VGA | |||
= T 132x44 9x8 . mono . . Ahead Systems EGA2001 | |||
= T 132x44 9x8 . 4 2 B800 Ahead B | |||
= T 132x60 . . 16 . . MORSE VGA | |||
= T 132x60 . . . . . Cirrus 510/520 chipset | |||
= G 80x25 8x19 640x480 16 1 A000 AX VGA (Kanji&superimpose) | |||
= G 94x29 8x14 752x410 16 . . ATI EGA Wonder | |||
= G 100x75 8x8 800x600 16 1 A000 OAK Technologies VGA-16 | |||
= G 100x75 8x8 800x600 16 . A000 Oak OTI-037 chipset [8] | |||
= G 100x37 8x16 800x600 16 . A000 Oak OTI-067/077 chips [8] | |||
= G 100x75 8x8 800x600 16 . A000 UM587 chipset | |||
= G 128x30 8x16 1024x480 16 . . NEL Electronics BIOS | |||
53h = T 80x25 8x16 . . . . NEL Electronics BIOS | |||
= T 80x60 . . 16 . . MORSE VGA | |||
= T 80x60 . . . . . Cirrus 510/520 chipset | |||
= T 132x25 8x14 . 16/256K . B800 Trident TVGA 8800/8900 | |||
= T 132x43 . . . . . Lava Chrome II EGA | |||
= G 80x25 8x19 640x480 16 1 A000 AX VGA (Kanji, no superimp.) | |||
= G . . 640x480 256 . . Oak VGA | |||
= G 80x30 8x16 640x480 256 . A000 Oak OTI-067/OTI-077 [8] | |||
= G 100x40 8x14 800x560 16 . . ATI EGA Wonder,ATI VIP | |||
= G . . . . . . AX PC | |||
54h = T 132x25 . . . . . Lava Chrome II EGA | |||
= T 132x30 8x16 . 16/256K . B800 Trident TVGA 8800/8900 | |||
= T 132x43 8x8 . . . . Paradise EGA-480 | |||
= T 132x43 8x8 . . . . NEL Electronics BIOS | |||
= T 132x43 7x9 . 16/256K . B800 Paradise VGA | |||
= T 132x43 8x9 . 16/256K . B800 Paradise VGA on multisync | |||
= T 132x43 . . . . . Taxan 565 EGA | |||
= T 132x43 . . . . . AST VGA Plus | |||
= T 132x43 . . . . . Hewlett-Packard D1180A | |||
= T 132x43 7x9 . 16 . . AT&T VDC600 | |||
= T 132x43 9x9 1188x387 16/256K . B800 WD90C | |||
= T 132x43 9x9 1188x387 16/256K . B800 Diamond Speedstar 24X | |||
= T 132x43 9x9 1188x387 16/256K . B800 Diamond Stealth 24 | |||
= T 132x43 8x8 . . . B800 Diamond Stealth64 Video 2xx1 | |||
= T 132x43 8x8 1056x350 16/256K . . Cirrus CL-GD5420/5422/5426 | |||
= T 132x50 8x8 . 16 . A000 NCR 77C22 [9] | |||
= G 100x42 8x14 800x600 16 . A000 ATI EGA Wonder, VGA Wonder | |||
= G 100x42 8x14 800x600 16 . A000 ATI Ultra 8514A, ATI XL | |||
= G . . 800x600 256 . A000 Oak VGA | |||
= G 100x37 8x16 800x600 256 . A000 Oak OTI-067/077 chips [8] | |||
55h = T 80x66 8x8 . 16/256K . A000 ATI VIP | |||
= T 132x25 8x14 . . . . Paradise EGA-480 | |||
= T 132x25 8x14 . . . . NEL Electronics BIOS | |||
= T 132x25 7x16 . 16/256K . B800 Paradise VGA | |||
= T 132x25 8x16 . 16/256K . B800 Paradise VGA on multisync | |||
= T 132x25 . . . . . Taxan 565 EGA | |||
= T 132x25 . . . . . AST VGA Plus | |||
= T 132x25 . . . . . Hewlett-Packard D1180A | |||
= T 132x25 7x16 . 16 . . AT&T VDC600 | |||
= T 132x25 8x16 . 16 . A000 NCR 77C22 [9] | |||
= T 132x25 9x16 1188x400 16/256K . B800 WD90C | |||
= T 132x25 9x16 1188x400 16/256K . B800 Diamond Speedstar 24X | |||
= T 132x25 9x16 1188x400 16/256K . B800 Diamond Stealth 24 | |||
= T 132x25 8x16 . . . B800 Diamond Stealth64 Video 2xx1 | |||
= T 132x25 8x14 1056x350 16/256K . . Cirrus CL-GD5420/5422/5426 | |||
= T 132x43 8x11 . 16/256K . B800 Trident TVGA 8800/8900 | |||
= G 94x29 8x14 752x410 . . . Lava Chrome II EGA | |||
= G 128x48 8x16 1024x768 16/256K . A000 ATI VGA Wonder v4+ [5] | |||
= G . . 1024x768 16/256K . . ATI VGA Wonder Plus | |||
= G . . 1024x768 16/256K . . ATI Ultra 8514A,ATI XL | |||
= G 128x48 8x16 1024x768 4 . A000 Oak OTI-067/077 chips [8] | |||
56h = T 132x43 8x8 . 3??? 2 B000 NSI Smart EGA+ | |||
= T 132x43 7x9 . 4 . B000 Paradise VGA | |||
= T 132x43 8x9 . 4 . B000 Paradise VGA on multisync | |||
= T 132x43 . . mono . . Taxan 565 EGA | |||
= T 132x43 7x9 . 2 . . AT&T VDC600 | |||
= T 132x43 9x8 . . . . NEL Electronics BIOS | |||
= T 132x50 8x8 . 4 . A000 NCR 77C22 [9] | |||
= T 132x60 8x8 . 16/256K . B800 Trident TVGA 8800/8900 | |||
= G . . 1024x768 16 . A000 Oak VGA | |||
= G 128x48 8x16 1024x768 16 . A000 Oak OTI-067/077 chips [8] | |||
57h = T 132x25 8x14 . 3??? 4 B000 NSI Smart EGA+ | |||
= T 132x25 7x16 . 4 . B000 Paradise VGA | |||
= T 132x25 8x16 . 4 . B000 Paradise VGA on multisync | |||
= T 132x25 9x14 . . . . NEL Electronics BIOS | |||
= T 132x25 . . mono . . Taxan 565 EGA | |||
= T 132x25 7x16 . 2 . . AT&T VDC600 | |||
= T 132x25 9x14 . 16/256K . B800 Trident TVGA 8800/8900 | |||
= T 132x25 8x16 . 4 . A000 NCR 77C22 [9] | |||
= G 96x48 8x16 768x1024 16 . A000 Oak OTI-067/077 chips [8] | |||
58h = T 80x33 8x14 . 16 . B800 ATI EGA Wonder,ATI VIP | |||
= T 80x32 9x16 . 16 . . Genoa 6400 | |||
= T 80x43 8x8 . . . . NEL Electronics BIOS | |||
= T 132x30 9x16 . 16/256K . B800 Trident TVGA 8800/8900 | |||
= G 100x75 8x8 800x600 16/256K . A000 Paradise VGA | |||
= G 100x75 8x8 800x600 16 . . AT&T VDC600 | |||
= G 100x75 8x8 800x600 16 . A000 NCR 77C22 [9] | |||
= G 100x75 8x8 800x600 16 . A000 Diamond Speedstar 24X | |||
= G 100x75 8x8 800x600 16/256K . A000 Paradise VGA, WD90C | |||
= G . . 800x600 16 . . AST VGA Plus, Compaq VGA | |||
= G . . 800x600 16 . . Dell VGA | |||
= G . . 800x600 16 . . Hewlett-Packard D1180A | |||
= G . . 800x600 ??? . . ELT VGA PLUS 16 | |||
= G 100x37 8x16 800x600 16/256K . A000 Cirrus CL-GD5420/5422/5426 | |||
= G 160x64 8x16 1280x1024 16 . A000 Oak OTI-077 chipset [8] | |||
59h = T 80x43 9x8 . . . . NEL Electronics BIOS | |||
= T 80x66 8x8 . 16/256K . A000 ATI VIP | |||
= T 132x43 9x11 . 16/256K . B800 Trident TVGA 8800/8900 | |||
= G 100x75 8x8 800x600 2 . A000 Paradise VGA | |||
= G 100x75 8x8 800x600 2 . . AT&T VDC600 | |||
= G . . 800x600 2 . . AST VGA Plus, Compaq VGA | |||
= G . . 800x600 2 . . Dell VGA | |||
= G . . 800x600 2 . . Hewlett-Packard D1180A | |||
= G 100x75 8x8 800x600 2 . A000 NCR 77C22 [9] | |||
= G 128x48 8x16 1024x768 256 . A000 Oak OTI-077 chipset [8] | |||
5Ah = T 80x60 8x8 . . . . NEL Electronics BIOS | |||
= T 132x60 9x8 . 16/256K . B800 Trident TVGA 8800/8900 | |||
= G 128x48 8x16 1024x768 2 . A000 NCR 77C22 [9] | |||
5Bh = T 80x30 8x16 . . . B800 ATI VGA Wonder (undoc) | |||
= G . . 640x350 256 . . Genoa 6400 | |||
= G 80x25 8x16 640x400 32K . A000 Oak OTI-067/077 chips [8] | |||
= G . . 800x600 16 . . Maxxon, SEFCO TVGA, Imtec | |||
= G 100x75 8x8 800x600 16/256K . A000 Trident TVGA 8800, 8900 | |||
= G . . 800x600 ??? . . Vobis MVGA | |||
= G 100x37 8x16 800x600 . . . NEL Electronics BIOS | |||
= G 128x48 8x16 1024x768 16 . A000 NCR 77C22 [1,9] | |||
5Ch = T 100x37 8x16 . . . . NEL Electronics BIOS | |||
= G . . 640x400 256 . . Logix, ATI Prism Elite | |||
= G . . 640x400 256 . . Maxxon, SEFCO TVGA, Imtec | |||
= G 80x25 8x16 640x400 256/256K . A000 Zymos Poach, Hi Res 512 | |||
= G 80x25 8x16 640x400 256/256K . A000 Trident TVGA 8800/8900 | |||
= G 80x30 8x16 640x480 256 . . Genoa 6400 | |||
= G 80x30 8x16 640x480 32K . A000 Oak OTI-077 chipset [8] | |||
= G 100x75 8x8 800x600 256 . A000 NCR 77C22 [9] | |||
= G 100x75 8x8 800x600 256/256K . A000 WD90C | |||
= G 100x75 8x8 800x600 256/256K . A000 Diamond Speedstar 24X | |||
= G 100x37 8x16 800x600 256/256K . A000 Cirrus CL-GD5420/5422/5426 | |||
5Dh = T 100x75 8x8 . . . . NEL Electronics BIOS | |||
= G 80x25 8x14 640x350 64K . . STB Lightspeed ET4000/W32P | |||
= G . . 640x480 256 . . Logix, ATI Prism Elite | |||
= G . . 640x480 256 . . Maxxon, SEFCO TVGA, Imtec | |||
= G 80x30 8x16 640x480 256/256K . A000 Zymos Poach, Hi Res 512 | |||
= G 80x30 8x16 640x480 256/256K . A000 Trident TVGA 8800 (512K) | |||
= G 128x48 8x16 1024x768 16 . A000 NCR 77C22 [9] | |||
= G 128x48 8x16 1024x768 16/256K . A000 WD90C | |||
= G 128x48 8x16 1024x768 16 . A000 Diamond Speedstar 24X | |||
= G 128x48 8x16 1024x768 16/256K . A000 Cirrus CL-GD5420/5422/5426 | |||
5Eh = G . . 640x400 256 . . Paradise VGA,VEGA VGA | |||
= G . . 640x400 256 . . AST VGA Plus, NCR 77C22 | |||
= G . . 640x400 256 . . Compaq VGA, Dell VGA | |||
= G 80x25 8x16 640x400 256 . . AT&T VDC600 | |||
= G 80x25 8x16 640x400 256 . A000 NCR 77C22 [9] | |||
= G 80x25 8x16 640x400 256/256K . A000 WD90C | |||
= G 80x25 8x16 640x400 256/256K . A000 Diamond Speedstar 24X | |||
= G . . 800x600 16 . . Logix, ATI Prism Elite | |||
= G 100x37 8x16 800x600 16 . . NEL Electronics BIOS | |||
= G 100x75 8x8 800x600 256 . . Genoa 6400 | |||
= G 100x75 8x8 800x600 256/256K . A000 Zymos Poach, Trident 8900 | |||
= G 100x75 8x8 800x600 256/256K . A000 Hi Res 512 | |||
5Fh = G 80x25 8x16 640x400 64K . . STB Lightspeed ET4000/W32P | |||
= G . . 640x480 256 . . Paradise VGA | |||
= G . . 640x480 256 . . AST VGA Plus, NCR 77C22 | |||
= G . . 640x480 256 . . Compaq VGA, Dell VGA | |||
= G . . 640x480 256 . . Hewlett-Packard D1180A | |||
= G 80x30 8x16 640x480 256 . . AT&T VDC600 (512K) | |||
= G 80x30 8x16 640x480 256 . A000 NCR 77C22 [9] | |||
= G 80x30 8x16 640x480 256/256K . A000 WD90C | |||
= G 80x30 8x16 640x480 256/256K . A000 Diamond Speedstar 24X | |||
= G 80x30 8x16 640x480 256/256K . A000 Cirrus CL-GD5420/5422/5426 | |||
= G . . 1024x768 16 . . Logix, ATI Prism Elite | |||
= G . . 1024x768 16 . . Maxxon, Imtec | |||
= G 128x48 8x16 1024x768 16 . . Genoa 6400 | |||
= G 128x48 8x16 1024x768 16/256K . A000 Zymos Poach, Hi Res 512 | |||
= G 128x48 8x16 1024x768 16/256K . A000 Trident TVGA 88/8900 512K | |||
60h = T 132x25 8x14 . 16/64 8 B800 Quadram Ultra VGA | |||
= T 132x25 8x14 . 16 . . Genoa 6400 | |||
= T 132x25 8x14 . 16 . . Genoa SuperEGA BIOS 3.0+ | |||
= T 132x25 . . . . . Cirrus 5320 chipset | |||
= T 132x25 8x16 1056x400 16 . B800 Chips&Technologies chipset | |||
= G 80x??? . ???x400 . . . Corona/Cordata BIOS 4.10+ | |||
= G 80x25 8x16 640x400 256 1 A000 Ahead A, Ahead B | |||
= G . . 752x410 . . . VEGA VGA | |||
= G . . 752x410 16 . . Tatung VGA | |||
= G . . 752x410 16 . . Video7 V-RAM VGA | |||
= G 128x48 8x16 1024x768 4/256K . A000 Trident TVGA 8900 | |||
= G 128x48 8x16 1024x768 256/256K . A000 WD90C | |||
= G 128x48 8x16 1024x768 256/256K . A000 Diamond Speedstar 24X | |||
= G 128x48 8x16 1024x768 256/256K . A000 Cirrus CL-GD5420/5422/5426 | |||
= G 144x54 8x16 1152x864 . . A000 Diamond Stealth64 Video 2xx1 | |||
61h = T 132x29 8x12 . 16/64 8 B800 Quadram Ultra VGA | |||
= T 132x29 8x8 . 16 . . Genoa 6400 | |||
= T 132x29 8x8 . 16 . . Genoa SuperEGA BIOS 3.0+ | |||
= T 132x50 . . . . . Cirrus 5320 chipset | |||
= T 132x50 8x8 1056x400 16 . B800 Chips&Technologies chipset | |||
= T 132x50 8x16 1056x800 16 . B800 Chips&Technologies 64310 | |||
= G . . ???x400 . . . Corona/Cordata BIOS 4.10+ | |||
= G 80x25 8x16 640x400 256 . A000 ATI VGA Wonder,VGA Wonder+ | |||
= G 80x25 8x16 640x400 256 . A000 ATI Ultra 8514A,ATI XL | |||
= G 80x25 8x16 640x400 . . A000 Diamond Stealth64 Video 2xx1 | |||
= G 80x30 8x16 640x480 256 1 A000 Ahead A, Ahead B (512K) | |||
= G . . 720x540 . . . VEGA VGA | |||
= G . . 720x540 16 . . Tatung VGA | |||
= G . . 720x540 16 . . Video7 V-RAM VGA | |||
= G 96x64 8x16 768x1024 16/256K . A000 Trident TVGA 88/8900 512K | |||
= G 128x48 8x16 1024x768 256 . A000 NCR 77C22 [1,9] | |||
= G 144x54 8x16 1152x864 . . A000 Diamond Stealth64 Video 2xx1 | |||
62h = T 132x32 8x11 . 16/64 6 B800 Quadram Ultra VGA | |||
= T 132x32 8x12 . 16 . . Genoa 6400 | |||
= T 132x32 8x11 . 16 . . Genoa SuperEGA BIOS 3.0+ | |||
= T 132x43 8x8 1056x344 16 . B800 C&T 82C450 BIOS | |||
= G . . 640x450 16 . . Cirrus 510/520 chipset | |||
= G 80x30 8x16 640x480 256 . A000 ATI VGA Wonder,VGA Wonder+ | |||
= G 80x30 8x16 640x480 256 . A000 ATI Ultra 8514A,ATI XL | |||
= G 80x30 8x16 640x480 32K . A000 WD90C | |||
= G 80x30 8x16 640x480 32K . A000 Diamond Speedstar 24X | |||
= G . . 800x600 . . . VEGA VGA | |||
= G . . 800x600 16 . . Tatung VGA | |||
= G . . 800x600 16 . . Video7 V-RAM VGA | |||
= G 100x75 8x8 800x600 256 1 A000 Ahead A, Ahead B (512K) | |||
= G 128x48 8x16 1024x768 256/256K . A000 Trident TVGA 8900, Zymos | |||
= G 128x48 8x16 1024x768 256 . A000 NCR 77C22 [9] | |||
63h = T 132x44 8x8 . 16/64 5 B800 Quadram Ultra VGA | |||
= T 132x44 8x8 . 16 . . Genoa 6400 | |||
= T 132x44 8x8 . 16 . . Genoa SuperEGA BIOS 3.0+ | |||
= G . . 720x540 16 . . MORSE VGA | |||
= G . . 720x540 16 . . Cirrus 510/520 chipset | |||
= G 100x42 8x14 800x600 256 . A000 ATI VGA Wonder,VGA Wonder+ | |||
= G 100x42 8x14 800x600 256 . A000 ATI Ultra 8514A,ATI XL | |||
= G . . 800x600 32K . A000 WD90C | |||
= G . . 800x600 32K . A000 Diamond Speedstar 24X | |||
= G 128x48 7x16 1024x768 256 1 A000 Ahead B (1MB) | |||
= G . . 1024x768 2 . . Video7 V-RAM VGA | |||
64h = T 132x60 8x8 . 16 . . Genoa 6400 | |||
= T 80x43 8x8 528x344 16 . B800 C&T 82C450 BIOS | |||
= G . . 640x480 64K . A000 Cirrus CL-GD 5422/5426 | |||
= G . . 800x600 16 . . MORSE VGA | |||
= G . . 800x600 16 . . Cirrus 510/520 chipset | |||
= G . . 800x600 ??? . . SAMPO-Mira VGA | |||
= G . . 1024x768 4 . . Video7 V-RAM VGA | |||
= G 128x48 8x16 1024x768 256 . A000 ATI VGA Wonder Plus,ATI XL | |||
= G 160x64 8x16 1280x1024 16/256K . A000 WD90C [1] | |||
= G 160x64 8x16 1280x1024 16/256K . A000 Diamond Speedstar 24X [1] | |||
65h = T 80x50 8x8 528x400 16 . B800 C&T 82C450 BIOS | |||
= G . . 800x600 64K . A000 Cirrus CL-GD 5422/5426 | |||
= G . . 1024x768 16 . . Video7 V-RAM VGA | |||
= G 128x48 8x16 1024x768 16 . A000 ATI VGA Wonder | |||
66h = T 80x50 8x8 640x400 16/256K . B800 WD90C | |||
= T 80x50 8x8 . 16 . B800 Diamond Speedstar 24X | |||
= G . . 640x400 256 . . Tatung VGA | |||
= G . . 640x400 256 . . Video7 V-RAM VGA | |||
= G . . 640x480 32K . A000 Cirrus CL-GD 5422/5426 | |||
67h = T 80x43 8x8 640x344 16/256K . B800 WD90C | |||
= T 80x43 8x8 . 16 . B800 Diamond Speedstar 24X | |||
= G . . 640x480 256 . . Video7 V-RAM VGA | |||
= G . . 800x600 32K . A000 Cirrus CL-GD 5422/5426 | |||
= G 128x48 8x16 1024x768 4 . A000 ATI VGA Wonder | |||
= G 160x64 8x16 1280x1024 16 . A000 NCR 77C22 [1,9] | |||
68h = G 80x25 8x16 640x400 . . A000 Diamond Stealth64 Video 2xx1 | |||
69h = T 132x50 8x8 1056x400 16/256K . B800 WD90C | |||
= T 132x50 8x8 . 16 . B800 Diamond Speedstar 24X | |||
= G 80x30 8x16 640x480 . . A000 Diamond Stealth64 Video 2xx1 | |||
= G . . 720x540 256 . A000 Video7 V-RAM VGA | |||
6Ah = G . . 800x600 16 . A000 VESA standard interface | |||
= G 100x75 8x8 800x600 16 . A000 Genoa 6400 | |||
= G 100x75 8x8 800x600 16 . A000 Diamond Speedstar 24X | |||
= G . . 800x600 16 . A000 Ahead A | |||
= G 100x75 8x8 800x600 16 1 A000 Ahead B (VESA) [see 71h] | |||
= G . . 800x600 16 . . Zymos Poach, Hi Res 512 | |||
= G . . 800x600 16 . . Epson LT-386SX in CRT Mode | |||
= G . . 800x600 16 . . Compuadd 316SL in CRT Mode | |||
= G 100x37 8x16 800x600 16/256K . A000 Cirrus CL-GD5420/5422/5426 | |||
= G 100x37 8x16 800x600 16 . A000 Diamond Stealth64 Video 2xx1 | |||
= G 100x42 8x14 800x600 . . A000 ATI VGA Wonder (undoc) | |||
= G . . 800x600 16 . A000 Chips&Technologies chipset | |||
= G 160x64 8x16 1280x1024 256 . A000 NCR 77C22 [1,9] | |||
6Bh = T 100x37 8x16 . 16 . . Genoa 6400 | |||
= T 100x37 8x16 . . . . NEL Electronics BIOS | |||
= G 100x37 8x16 800x600 . . A000 Diamond Stealth64 Video 2xx1 | |||
6Ch = G 80x30 8x16 640x480 16M . A000 Trident 8900CL/BIOS C04 | |||
= G 100x75 8x8 800x600 256 . . Genoa 6400 | |||
= G 128x48 8x16 1024x768 2 . A000 Diamond Stealth64 Video 2xx1 | |||
= G 160x60 8x16 1280x960 16/256K . A000 WD90C [1] | |||
= G 160x60 8x16 1280x960 16/256K . A000 Diamond Speedstar 24X [1] | |||
= G 160x64 8x16 1280x1024 16/256K . A000 Cirrus CL-GD 5422/5426 [1] | |||
6Dh = G 80x25 8x14 640x350 64K . A000 STB Lightspeed ET4000/W32P | |||
= G 128x48 8x16 1024x768 . . A000 Diamond Stealth64 Video 2xx1 | |||
= G 160x64 8x16 1280x1024 256/256K . A000 Cirrus CL-GD 5422/5426 [1] | |||
6Eh = G 40x25 8x8 320x200 64K . A000 Cirrus CL-GD 5422/5426 | |||
= G 160x64 8x16 1280x1024 2 . A000 Diamond Stealth64 Video 2xx1 | |||
6Fh = G 40x25 8x8 320x200 16M . A000 Cirrus CL-GD 5422/5426 | |||
= G 160x64 8x16 1280x1024 . . A000 Diamond Stealth64 Video 2xx1 | |||
70h = extended mode set (see AX=0070h) . Everex Micro Enhancer EGA | |||
= T 40x25 8x8 . 16 8 B800 Quadram (CGA double scan) | |||
= T 40x25 8x8 (CGA dblscan) . . Genoa SuperEGA BIOS 3.0+ | |||
= G . . 360x480 256 . . Cirrus 510/520/5320 chips | |||
= G 90x28 8x14 720x392 16 1 A000 Ahead B | |||
= G 80x30 8x16 640x480 . . A000 Diamond Stealth64 Video 2xx1 | |||
= G 100x38 8x16 800x600 16 . A000 C&T chipset, Cardinal | |||
= G . . 1024x480 256 . A000 Trident 8900C BIOS C3.0 | |||
71h = T 80x25 8x8 . 16 8 B800 Quadram (CGA double scan) | |||
= T 80x25 8x8 (CGA dblscan) . . Genoa SuperEGA BIOS 3.0+ | |||
= G . . 528x400 256 . . Cirrus 510/520 chipset | |||
= G 80x30 8x16 640x480 16M . A000 Cirrus CL-GD 5422/5426 | |||
= G 80x30 8x16 640x480 . . A000 Diamond Stealth64 Video 2xx1 | |||
= G 100x35 8x16 800x600 16/64 . A000 NSI Smart EGA+ | |||
= G 100x75 8x8 800x600 16 1 A000 Ahead B (same as 6Ah) | |||
= G . . 960x720 16 . . C&T chipset, Cardinal | |||
= G . . 1024x480 256 . A000 Trident 8900C BIOS C3.0 | |||
72h = T 80x60 8x8 . 16 . B800 Quadram Ultra VGA | |||
= T 80x60 8x8 . 16 . B800 Genoa 6400 | |||
= T 80x60 8x8 . 16 . B800 Genoa SuperEGA BIOS 3.0+ | |||
= G . . 528x480 256 . . Cirrus 510/520 chipset | |||
= G 80x25 8x19 640x480 16 1 A000 DOS/V w/ any VGA | |||
= G 80x30 8x16 640x480 . . A000 Diamond Stealth64 Video 2xx1 | |||
= G . . 640x480 32K . A000 ATI | |||
= G . . 640x480 16M . A000 WD90C | |||
= G . . 640x480 16M . A000 Diamond Speedstar 24X | |||
= G . . 1024x768 16 . . C&T chipset, Cardinal | |||
= G 128x48 8x16 1024x768i 16 . A000 C&T 82C450 BIOS | |||
= G 128x48 8x16 1024x768 16 . A000 C&T 65530 BIOS (multisync) | |||
73h = G 80x60 8x8 640x480 16 . A000 Quadram Ultra VGA | |||
= G 80x60 8x8 640x480 16 . . Genoa 6400 | |||
= G 80x60 8x8 640x480 16 . . Genoa SuperEGA BIOS 3.0+ | |||
= G 100x37 8x16 800x600 . . A000 Diamond Stealth64 Video 2xx1 | |||
= T 80x25 8x19 640x475 16 1 none DOS/V, emulated in VGA graph | |||
74h = T 80x66 8x8 . 16 . B800 Quadram Ultra VGA | |||
= T 80x66 8x8 . 16 . B800 Genoa 6400 | |||
= T 80x66 8x8 . 16 . B800 Genoa SuperEGA BIOS 3.0+ | |||
= G . . 640x400 2 . B800 Toshiba 3100 AT&T mode | |||
= G 80x30 8x16 640x480 32K . A000 Trident 8900C/BIOS C03 | |||
= G 100x37 8x16 800x600 . . A000 Diamond Stealth64 Video 2xx1 | |||
= G 128x48 8x16 1024x768 16 1 A000 Ahead A, Ahead B (512K) | |||
= G . . 1024x768 64K . A000 Cirrus CL-GD 5422/5426 [1] | |||
75h = G 80x30 8x16 640x480 64K . A000 Trident 8900C/BIOS C03 | |||
= G 80x66 . 640x528 16??? . A000 Quadram Ultra VGA | |||
= G 80x66 . 640x528 16 . . Genoa SuperEGA BIOS 3.0+ | |||
= G 100x37 8x16 800x600 . . A000 Diamond Stealth64 Video 2xx1 | |||
= G 128x48 8x16 1024x768 4 1 A000 Ahead B | |||
= G 128x48 8x16 1024x768 16 . A000 Chips&Technologies 64310 | |||
76h = T 94x29 8x14 . 16 . B800 Quadram Ultra VGA | |||
= T 94x29 8x14 . . . . Genoa SuperEGA BIOS 3.0+ | |||
= G 100x75 8x8 800x600 32K . A000 Trident 8900C/BIOS C03 | |||
= G 128x48 8x16 1024x768 2 1 A000 Ahead B | |||
= G 128x48 8x16 1024x768 . . A000 Diamond Stealth64 Video 2xx1 | |||
= G 160x64 8x16 1280x1024 16 . A000 Chips&Technologies 64310 [1] | |||
77h = G 94x29 . 752x410 16??? . A000 Quadram Ultra VGA | |||
= G 94x29 . 752x410 16 . . Genoa SuperEGA BIOS 3.0+ | |||
= G 100x75 8x8 800x600 64K . A000 Trident 8900C/BIOS C03 | |||
= G 128x48 8x16 1024x768 . . A000 Diamond Stealth64 Video 2xx1 | |||
78h = T 100x37 8x16 . 16 . . Genoa 6400 | |||
= T 100x75 8x8 . 16 . B800 Quadram Ultra VGA | |||
= T 100x75 8x8 . . . . Genoa SuperEGA BIOS 3.0+ | |||
= G . . 640x400 256 . . STB VGA/EM-16 Plus | |||
= G 80x25 8x16 640x400 256 . . Cardinal, C&T chipset | |||
= G . . 640x400 256 . . Cirrus 5320 chipset | |||
= G 80x25 8x16 640x400 256 . A000 Chips&Technologies 64310 | |||
79h = G 80x30 8x16 640x480 256 . . Cardinal, C&T chipset | |||
= G 80x30 8x16 640x480 256 . A000 Chips&Technologies 64310 | |||
= G 100x75 . 800x600 16??? . A000 Quadram Ultra VGA | |||
= G 100x75 8x8 800x600 16 . . Genoa SuperEGA BIOS 3.0+ | |||
= G 100x75 8x8 800x600 16 . . Genoa 6400 | |||
7Ah = T 114x60 8x8 . 16 . B800 Quadram Ultra VGA | |||
= T 114x60 8x8 . . . . Genoa SuperEGA BIOS 3.0+ | |||
= G . . 720x540 256 . . C&T chipset, Cardinal | |||
7Bh = G . . 800x600 256 . . C&T chipset, Cardinal | |||
= G 114x60 . 912x480 16??? . A000 Quadram Ultra VGA | |||
= G . . 912x480 16 . . Genoa SuperEGA BIOS 3.0+ | |||
7Ch = G . . 512x512 16 . . Genoa | |||
= G 100x37 8x16 800x600 256 . . C&T 82C453/F65530 chipsets | |||
= G 100x37 8x16 800x600 256 . A000 Chips&Technologies 64310 | |||
= G 200x75 8x16 1600x1200 . [16] . A000 Diamond Stealth64 Video 2xx1 | |||
7Dh = G 64x32 8x16 512x512 256 . . Genoa | |||
7Eh = special mode set (see AX=007Eh) . Paradise VGA, AT&T VDC600 | |||
= G 80x25 8x16 640x400 256 . . Genoa 6400 | |||
= G . . 1024x768 256 . . C&T 82C453 chipset | |||
= G 128x48 8x16 1024x768 256 . A000 Chips&Technologies 64310 | |||
= G 90x43 . . mono . B000 HERCULES.COM on HGC [14] | |||
7Fh = special function set (see AX=007Fh/BH=00h) Paradise VGA, AT&T VDC600 | |||
= G 128x48 8x16 1024x768 4 . . Genoa 6400 | |||
= G 90x29 . . mono . B000 HERCULES.COM on HGC [14] | |||
82h = T 80x25 . . B&W . . AT&T VDC overlay mode [6] | |||
83h = T 80x25 . . . . . AT&T VDC overlay mode [6] | |||
86h = G . . 640x200 B&W . . AT&T VDC overlay mode [6] | |||
88h = G 90x43 8x8 720x348 mono . B000 Hercules + MSHERC.COM | |||
C0h = G . . 640x400 2/prog palette . AT&T VDC overlay mode [6] | |||
= G . . 640x400 2/prog palette . Olivetti Quaderno overlay | |||
C4h = disable output . . . . AT&T VDC overlay mode [6] | |||
C8h = G 80x50 8x8 640x400 2 . B800 Olivetti Quaderno overlay | |||
D0h = G . . 640x400 2 . B800 DEC VAXmate AT&T mode | |||
Notes: | |||
[1] interlaced only | |||
[2] for ATI EGA Wonder, mode 08h is only valid if SMS.COM is loaded resident. | |||
SMS maps mode 08h to mode 27h if the byte at location 0040:0063 is 0B4h, | |||
otherwise to mode 23h, thus selecting the appropriate (monochrome or | |||
color) 132x25 character mode. | |||
for ATI VGA Wonder, mode 08h is the same, and only valid if VCONFIG loaded | |||
resident | |||
[3] early XGA boards support 132-column text but do not have this BIOS mode | |||
[4] DESQview intercepts calls to change into these two modes (21h is page 0, | |||
22h is page 1) even if there is no Hercules graphics board installed | |||
[5] ATI BIOS v4-1.00 has a text-scrolling bug in this mode | |||
[6] for AT&T VDC overlay modes, BL contains the DEB mode, which may be 06h, | |||
40h, or 44h | |||
[7] BIOS text support is broken in this undocumented mode; scrolling moves | |||
only about 1/3 of the screen (and does even that portion incorrectly), | |||
while screen clears only clear about 3/4. | |||
[8] The Oak OTI-037/067/077 modes are present in the Oak VGA BIOS, which OEMs | |||
may choose to use only partially or not at all; thus, not all Oak boards | |||
support all "Oak" modes listed here | |||
[9] this card uses the full 128K A000h-BFFFh range for the video buffer, | |||
precluding the use of a monochrome adapter in the same system | |||
[10] mode 17h supported by Tseng ET4000 BIOS 8.01X dated 1990/09/14, but not | |||
v8.01X dated 1992/02/28; mode 21h supported by 1992/02/28 version but not | |||
1990/09/14 version | |||
[11] HERKULES simulates a 90x45 text mode in Hercules graphics mode; the | |||
installation check for HERKULES.COM is the signature "Herkules" two | |||
bytes beyond the INT 10 handler | |||
[12] The Realtek RTVGA BIOS v3.C10 crashes when attempting to switch into | |||
modes 21h or 27h; this version of the BIOS also sets the BIOS data area | |||
incorrectly for extended text modes, resulting in scrolling after only | |||
24 lines (the VMODE.EXE utility does set the data area correctly) | |||
[13] The Tandy 1000SL/TL BIOS does not actually support this mode | |||
[14] HERCULES.COM is a graphics-mode BIOS extension for Hercules-compatible | |||
graphics cards by Soft Warehouse, Inc. Its installation check is to | |||
test whether the word preceding the INT 10 handler is 4137h. | |||
[15] The Hercules-graphics video modes for HERCBIOS (shareware by Dave | |||
Tutelman) may be changed by a command-line switch; the 90x43 | |||
character-cell mode's number is always one higher than the 90x29 mode | |||
(whose default is mode 08h) | |||
[16] Stealth64 Video 2001-series BIOS v1.03 reports 76 lines for mode 7Ch, | |||
resulting in incorrect scrolling for TTY output (scrolling occurs only | |||
after the end of the 76th line, which is not displayed) | |||
[17] For 43-line text on EGA or 43/50-line text on VGA, you must load an 8x8 | |||
font using AX=1102h after switching to mode 3; VGA may also require | |||
using INT 10/AH=12h/BL=30h |
@ -0,0 +1,762 @@ | |||
/***************************************************************************** | |||
VGA graphics demo | |||
Chris Giese <geezer@execpc.com> http://my.execpc.com/~geezer | |||
Release date: ? | |||
This code is public domain (no copyright). | |||
You can do whatever you want with it. | |||
This code uses the BIOS to set graphics mode, and uses the BIOS font. | |||
Should compile cleanly with Turbo C++ 1.0, Turbo C++ 3.0, 16- or 32-bit | |||
Watcom C, or DJGPP. DJGPP version will not work in Windows NT/2000/XP | |||
DOS box. | |||
Some additional things you could do with this: | |||
- Write a function tblit1(), similar to blit1(), that uses an on-off | |||
transparency mask. Use this function to blit non-rectangular objects | |||
such as a mouse cursor. | |||
- Write blit_plane(): a fast function to blit from monochrome to monochrome | |||
or 4-plane bitmaps. Use an external shift() function, written in asm | |||
- Support VBE 1.x banked framebuffer | |||
- Support VBE 2.x linear framebuffer (pmode only, not at A000h:0000) | |||
- Support greater color depths: 15 bpp, 16 bpp, 24 bpp, 32 bpp | |||
- Color reduction, e.g. Heckbert (median-cut) algorithm | |||
- Clipping engine that lets you draw a window that is partially | |||
obscured by "closer" windows | |||
- Mouse, keyboard, and timer events | |||
- Widgets: push button, checkbox, radio buttons, listbox, dialog, etc. | |||
*****************************************************************************/ | |||
#include <string.h> /* [_f]memset() */ | |||
/********************************* TURBO C **********************************/ | |||
#if defined(__TURBOC__) | |||
#include <dos.h> /* struct REGPACK, intr() */ | |||
/* The framebuffer is far outside the 16-bit data segment. The only way to | |||
make the framebuffer work like in-memory bitmaps is to use far pointers. | |||
We still use the SMALL memory model. */ | |||
#define FAR far | |||
#define FARPTR(S, O) MK_FP(S, O) | |||
#define outportw(P,V) outport(P,V) | |||
#define R_AX r_ax | |||
#define R_BX r_bx | |||
#define R_BP r_bp | |||
#define R_ES r_es | |||
#define trap(N,R) | |||
typedef struct regs_t; | |||
#if __TURBOC__<0x300 | |||
void vmemset(unsigned char FAR *s, unsigned c, unsigned n) | |||
{ | |||
for(; n != 0; n--) | |||
{ | |||
*s = c; | |||
s++; | |||
} | |||
} | |||
#else | |||
void vmemset(unsigned char FAR *s, unsigned c, unsigned n) | |||
{ | |||
_fmemset(s, c, n); | |||
} | |||
#endif | |||
/********************************* DJGPP ************************************/ | |||
#elif defined(__DJGPP__) | |||
#include <dpmi.h> /* __dpmi_... */ | |||
#include <dos.h> /* inportb(), outportb() */ | |||
#define FAR /* nothing */ | |||
#define FARPTR(S, O) (unsigned char *)((S) * 16L + (O) + \ | |||
__djgpp_conventional_base) | |||
/* near pointers; not supported in Windows NT/2k/XP DOS box */ | |||
#include <sys/nearptr.h> /* __djgpp_conventional_base, __djgpp_nearptr_enable() */ | |||
#include <stdio.h> /* printf() */ | |||
#include <crt0.h> /* _CRT0_FLAG_NEARPTR, _crt0_startup_flags */ | |||
#define R_AX x.ax | |||
#define R_BX x.bx | |||
#define R_BP x.bp | |||
#define R_ES x.es | |||
#define trap(N,R) __dpmi_int(N,R) | |||
typedef __dpmi_regs regs_t; | |||
void vmemset(unsigned char FAR *s, unsigned c, unsigned n) | |||
{ | |||
memset(s, c, n); | |||
} | |||
/******************************** WATCOM C **********************************/ | |||
#elif defined(__WATCOMC__) | |||
#include <dos.h> /* union REGPACK, MK_FP(), intr() */ | |||
#if defined(__386__) | |||
#define FAR /* nothing */ | |||
#define FARPTR(S, O) (unsigned char *)((S) * 16L + (O)) | |||
void vmemset(unsigned char FAR *s, unsigned c, unsigned n) | |||
{ | |||
memset(s, c, n); | |||
} | |||
#else | |||
#define FAR far | |||
#define FARPTR(S, O) MK_FP(S, O) | |||
void vmemset(unsigned char FAR *s, unsigned c, unsigned n) | |||
{ | |||
_fmemset(s, c, n); | |||
} | |||
#endif | |||
#define inportb(P) inp(P) | |||
#define outportb(P,V) outp(P,V) | |||
#define outportw(P,V) outpw(P,V) | |||
#define R_AX w.ax | |||
#define R_BX w.bx | |||
#define R_BP w.bp | |||
#define R_ES w.es | |||
/* WARNING: for 32-bit code, unused fields of regs_t | |||
must be zeroed before using this macro */ | |||
#define trap(N,R) intr(N,R) | |||
typedef union REGPACK regs_t; | |||
#else | |||
#error Not Turbo C, not DJGPP, not Watcom C. Sorry. | |||
#endif | |||
#include <conio.h> /* getch() */ | |||
/* need direct access to some VGA registers to select plane, | |||
enable Mode X, and fix screwy CGA addressing */ | |||
#define VGA_SEQ_INDEX 0x3C4 | |||
#define VGA_SEQ_DATA 0x3C5 | |||
#define VGA_GC_INDEX 0x3CE | |||
#define VGA_GC_DATA 0x3CF | |||
#define VGA_CRTC_INDEX 0x3D4 | |||
#define VGA_CRTC_DATA 0x3D5 | |||
/* bitmap "class" */ | |||
typedef struct | |||
{ | |||
unsigned wd, ht; | |||
unsigned char FAR *raster; | |||
unsigned fore_color, back_color; | |||
/* "member functions" */ | |||
const struct _driver *ops; | |||
} bmp_t; | |||
typedef struct _driver | |||
{ | |||
/* "pure virtual functions": color drivers MUST implement these */ | |||
void (*write_pixel)(bmp_t *bmp, unsigned x, unsigned y, unsigned c); | |||
unsigned (*read_pixel)(bmp_t *bmp, unsigned x, unsigned y); | |||
/* "virtual functions": drivers MAY implement these, for speed | |||
fill rectangular area with solid color */ | |||
void (*fill_rect)(bmp_t *bmp, int x, int y, int wd, int ht); | |||
/* copy monochrome bitmap to this bitmap (used to display text) */ | |||
void (*blit1)(bmp_t *src, bmp_t *dst, unsigned dst_x, unsigned dst_y); | |||
/* copy all or part of one bitmap to another (both of the same depth) */ | |||
void (*blit)(bmp_t *src, bmp_t *dst, unsigned dst_x, unsigned dst_y); | |||
} ops_t; | |||
/*============================================================================ | |||
helper functions | |||
============================================================================*/ | |||
/***************************************************************************** | |||
*****************************************************************************/ | |||
void set_plane(unsigned p) | |||
{ | |||
static unsigned curr_p = -1u; | |||
/**/ | |||
unsigned char pmask; | |||
p &= 3; | |||
if(p == curr_p) | |||
return; | |||
curr_p = p; | |||
pmask = 1 << p; | |||
#if 0 | |||
outportb(VGA_GC_INDEX, 4); | |||
outportb(VGA_GC_DATA, p); | |||
outportb(VGA_SEQ_INDEX, 2); | |||
outportb(VGA_SEQ_DATA, pmask); | |||
#else | |||
/* this is a little faster... */ | |||
outportw(VGA_GC_INDEX, (p << 8) | 4); | |||
outportw(VGA_SEQ_INDEX, (pmask << 8) | 2); | |||
#endif | |||
} | |||
/***************************************************************************** | |||
fast planar (monochrome or 16-color) rectangle fill | |||
*****************************************************************************/ | |||
void fill_plane(bmp_t *bmp, int x, int y, int wd, int ht, unsigned c) | |||
{ | |||
unsigned w, wd_in_bytes, off; | |||
unsigned char lmask, rmask; | |||
int x2, y2; | |||
x2 = x + wd - 1; | |||
w = (x2 >> 3) - (x >> 3) + 1; | |||
lmask = 0x00FF >> (x & 7); /* FF 7F 3F 1F 0F 07 03 01 */ | |||
rmask = 0xFF80 >> (x2 & 7);/* 80 C0 E0 F0 F8 FC FE FF */ | |||
if(w == 1) | |||
lmask &= rmask; | |||
wd_in_bytes = bmp->wd / 8; | |||
off = wd_in_bytes * y + x / 8; | |||
if(c) | |||
/* for each row... */ | |||
for(y2 = y; y2 < y + ht; y2++) | |||
{ | |||
/* do partial byte on left */ | |||
bmp->raster[off] |= lmask; | |||
/* do solid bytes in middle */ | |||
if(w > 2) | |||
vmemset(bmp->raster + off + 1, 0xFF, w - 2); | |||
/* do partial byte on right */ | |||
if(w > 1) | |||
bmp->raster[off + w - 1] |= rmask; | |||
/* next row */ | |||
off += wd_in_bytes; | |||
} | |||
else | |||
{ | |||
lmask = ~lmask; | |||
rmask = ~rmask; | |||
for(y2 = y; y2 < y + ht; y2++) | |||
{ | |||
bmp->raster[off] &= lmask; | |||
if(w > 2) | |||
vmemset(bmp->raster + off + 1, 0, w - 2); | |||
if(w > 1) | |||
bmp->raster[off + w - 1] &= rmask; | |||
off += wd_in_bytes; | |||
} | |||
} | |||
} | |||
/***************************************************************************** | |||
fast planar blit | |||
*****************************************************************************/ | |||
void blit_plane(bmp_t *src, bmp_t *dst, unsigned dst_x, unsigned dst_y) | |||
{ | |||
/* left as an exercise for the reader :) | |||
You may need an external, assembly-language function to shift (left or | |||
right) a long string of bytes. No need to shift by more than 7 bits. */ | |||
} | |||
/*============================================================================ | |||
driver for monochrome (1-bit) graphics | |||
============================================================================*/ | |||
/***************************************************************************** | |||
*****************************************************************************/ | |||
static void write_pixel1(bmp_t *bmp, unsigned x, unsigned y, unsigned c) | |||
{ | |||
unsigned wd_in_bytes; | |||
unsigned off, mask; | |||
c = (c & 1) * 0xFF; | |||
wd_in_bytes = bmp->wd / 8; | |||
off = wd_in_bytes * y + x / 8; | |||
x = (x & 7) * 1; | |||
mask = 0x80 >> x; | |||
bmp->raster[off] = (bmp->raster[off] & ~mask) | (c & mask); | |||
} | |||
/***************************************************************************** | |||
*****************************************************************************/ | |||
static unsigned read_pixel1(bmp_t *bmp, unsigned x, unsigned y) | |||
{ | |||
unsigned wd_in_bytes; | |||
unsigned off, mask; | |||
wd_in_bytes = bmp->wd / 8; | |||
off = wd_in_bytes * y + x / 8; | |||
x = (x & 7) * 1; | |||
mask = 0x80 >> x; | |||
return (bmp->raster[off] & mask) != 0; | |||
} | |||
/***************************************************************************** | |||
*****************************************************************************/ | |||
static void fill_rect1(bmp_t *bmp, int x, int y, int wd, int ht) | |||
{ | |||
fill_plane(bmp, x, y, wd, ht, bmp->fore_color & 1); | |||
} | |||
/***************************************************************************** | |||
*****************************************************************************/ | |||
const ops_t g_ops1 = | |||
{ | |||
write_pixel1, | |||
read_pixel1, | |||
fill_rect1, | |||
NULL, /* blit1 */ | |||
NULL /* blit */ | |||
}; | |||
/*============================================================================ | |||
driver for 2-bit packed pixel (4-color CGA) graphics | |||
============================================================================*/ | |||
/***************************************************************************** | |||
*****************************************************************************/ | |||
static void write_pixel2(bmp_t *bmp, unsigned x, unsigned y, unsigned c) | |||
{ | |||
unsigned wd_in_bytes, off, mask; | |||
c = (c & 3) * 0x55; | |||
wd_in_bytes = bmp->wd / 4; | |||
off = wd_in_bytes * y + x / 4; | |||
x = (x & 3) * 2; | |||
mask = 0xC0 >> x; | |||
bmp->raster[off] = (bmp->raster[off] & ~mask) | (c & mask); | |||
} | |||
/***************************************************************************** | |||
*****************************************************************************/ | |||
const ops_t g_ops2 = | |||
{ | |||
write_pixel2, | |||
NULL, /* read_pixel */ | |||
NULL, /* fill_rect */ | |||
NULL, /* blit1 */ | |||
NULL /* blit */ | |||
}; | |||
/*============================================================================ | |||
driver for 4-plane 16-color graphics | |||
============================================================================*/ | |||
/***************************************************************************** | |||
*****************************************************************************/ | |||
static void write_pixel4p(bmp_t *bmp, unsigned x, unsigned y, unsigned c) | |||
{ | |||
unsigned wd_in_bytes, off, mask, p, pmask; | |||
wd_in_bytes = bmp->wd / 8; | |||
off = wd_in_bytes * y + x / 8; | |||
x = (x & 7) * 1; | |||
mask = 0x80 >> x; | |||
pmask = 1; | |||
for(p = 0; p < 4; p++) | |||
{ | |||
set_plane(p); | |||
if(pmask & c) | |||
bmp->raster[off] |= mask; | |||
else | |||
bmp->raster[off] &= ~mask; | |||
pmask <<= 1; | |||
} | |||
} | |||
/***************************************************************************** | |||
pixel-by-pixel fill is too slow, so use this optimized function: | |||
*****************************************************************************/ | |||
static void fill_rect4p(bmp_t *bmp, int x, int y, int wd, int ht) | |||
{ | |||
unsigned char p, pmask; | |||
pmask = 1; | |||
for(p = 0; p < 4; p++) | |||
{ | |||
set_plane(p); | |||
fill_plane(bmp, x, y, wd, ht, bmp->fore_color & pmask); | |||
pmask <<= 1; | |||
} | |||
} | |||
/***************************************************************************** | |||
*****************************************************************************/ | |||
const ops_t g_ops4p = | |||
{ | |||
write_pixel4p, | |||
NULL, /* read_pixel */ | |||
fill_rect4p, | |||
NULL, /* blit1 */ | |||
NULL /* blit */ | |||
}; | |||
/*============================================================================ | |||
driver for 8-bit 256-color graphics | |||
============================================================================*/ | |||
/***************************************************************************** | |||
*****************************************************************************/ | |||
static void write_pixel8(bmp_t *bmp, unsigned x, unsigned y, unsigned c) | |||
{ | |||
unsigned wd_in_bytes; | |||
unsigned off; | |||
wd_in_bytes = bmp->wd; | |||
off = wd_in_bytes * y + x; | |||
bmp->raster[off] = c; | |||
} | |||
/***************************************************************************** | |||
*****************************************************************************/ | |||
static void fill_rect8(bmp_t *bmp, int x, int y, int wd, int ht) | |||
{ | |||
unsigned wd_in_bytes, off, y2; | |||
wd_in_bytes = bmp->wd; | |||
off = wd_in_bytes * y + x; | |||
for(y2 = y; y2 < y + ht; y2++) | |||
{ | |||
vmemset(bmp->raster + off, bmp->fore_color, wd); | |||
off += wd_in_bytes; | |||
} | |||
} | |||
/***************************************************************************** | |||
*****************************************************************************/ | |||
const ops_t g_ops8 = | |||
{ | |||
write_pixel8, | |||
NULL, /* read_pixel */ | |||
fill_rect8, | |||
NULL, /* blit1 */ | |||
NULL /* blit */ | |||
}; | |||
/*============================================================================ | |||
driver for 8-bit 256-color Mode-X graphics | |||
============================================================================*/ | |||
/***************************************************************************** | |||
*****************************************************************************/ | |||
static void write_pixel8x(bmp_t *bmp, unsigned x, unsigned y, unsigned c) | |||
{ | |||
unsigned wd_in_bytes; | |||
unsigned off; | |||
wd_in_bytes = bmp->wd / 4; | |||
off = wd_in_bytes * y + x / 4; | |||
set_plane(x & 3); | |||
bmp->raster[off] = c; | |||
} | |||
/***************************************************************************** | |||
*****************************************************************************/ | |||
const ops_t g_ops8x = | |||
{ | |||
write_pixel8x, | |||
NULL, /* read_pixel */ | |||
NULL, /* fill_rect */ | |||
NULL, /* blit1 */ | |||
NULL /* blit */ | |||
}; | |||
/*============================================================================ | |||
depth-independent routines, which call the depth-dependent routines | |||
============================================================================*/ | |||
/***************************************************************************** | |||
*****************************************************************************/ | |||
unsigned read_pixel(bmp_t *bmp, unsigned x, unsigned y) | |||
{ | |||
if(x >= bmp->wd || y >= bmp->ht) | |||
return 0; | |||
if(bmp->ops->read_pixel == NULL) | |||
return 0; /* uh-oh */ | |||
return bmp->ops->read_pixel(bmp, x, y); | |||
} | |||
/***************************************************************************** | |||
*****************************************************************************/ | |||
void write_pixel(bmp_t *bmp, unsigned x, unsigned y, unsigned c) | |||
{ | |||
if(x >= bmp->wd || y >= bmp->ht) | |||
return; | |||
if(bmp->ops->write_pixel == NULL) | |||
return; /* uh-oh */ | |||
bmp->ops->write_pixel(bmp, x, y, c); | |||
} | |||
/***************************************************************************** | |||
*****************************************************************************/ | |||
void fill_rect(bmp_t *bmp, int x, int y, int wd, int ht) | |||
{ | |||
int x2, y2; | |||
/* clip */ | |||
if(x < 0) | |||
{ | |||
if(wd + x < 0) | |||
return; | |||
wd += x; | |||
x = 0; | |||
} | |||
if(x + wd >= (int)bmp->wd) | |||
{ | |||
if(x >= (int)bmp->wd) | |||
return; | |||
wd = bmp->wd - x; | |||
} | |||
if(y < 0) | |||
{ | |||
if(ht + y < 0) | |||
return; | |||
ht += y; | |||
y = 0; | |||
} | |||
if(y + ht >= (int)bmp->ht) | |||
{ | |||
if(y >= (int)bmp->ht) | |||
return; | |||
ht = bmp->ht - y; | |||
} | |||
/* use fast routine if available */ | |||
if(bmp->ops->fill_rect != NULL) | |||
{ | |||
bmp->ops->fill_rect(bmp, x, y, wd, ht); | |||
return; | |||
} | |||
for(y2 = y; y2 < y + ht; y2++) | |||
for(x2 = x; x2 < x + wd; x2++) | |||
write_pixel(bmp, x2, y2, bmp->fore_color); | |||
} | |||
/***************************************************************************** | |||
*****************************************************************************/ | |||
void hline(bmp_t *bmp, int x, int y, unsigned wd) | |||
{ | |||
fill_rect(bmp, x, y, wd, 1); | |||
} | |||
/***************************************************************************** | |||
*****************************************************************************/ | |||
void vline(bmp_t *bmp, int x, int y, unsigned ht) | |||
{ | |||
fill_rect(bmp, x, y, 1, ht); | |||
} | |||
/***************************************************************************** | |||
blit1 = blit from monochrome bitmap to bitmap of any color depth | |||
*****************************************************************************/ | |||
void blit1(bmp_t *src, bmp_t *dst, unsigned dst_x, unsigned dst_y) | |||
{ | |||
unsigned x, y, c; | |||
/* source bitmap _must_ be monochrome */ | |||
if(src->ops != &g_ops1) | |||
return; | |||
/* use fast routine if available */ | |||
if(src->ops->blit1 != NULL) | |||
{ | |||
src->ops->blit1(src, dst, dst_x, dst_y); | |||
return; | |||
} | |||
for(y = 0; y < src->ht; y++) | |||
for(x = 0; x < src->wd; x++) | |||
{ | |||
c = read_pixel(src, x, y); | |||
/* xxx - on-off transparency? | |||
if(c == 0) | |||
continue; */ | |||
if(c != 0) | |||
c = dst->fore_color; | |||
else | |||
c = dst->back_color; | |||
write_pixel(dst, dst_x + x, dst_y + y, c); | |||
} | |||
} | |||
/***************************************************************************** | |||
blit = copy from one bitmap to another, both of the same color depth | |||
*****************************************************************************/ | |||
void blit(bmp_t *src, bmp_t *dst, unsigned dst_x, unsigned dst_y) | |||
{ | |||
unsigned x, y, c; | |||
/* they must be the same depth */ | |||
if(src->ops != dst->ops) | |||
return; | |||
/* use fast routine if available */ | |||
if(src->ops->blit != NULL) | |||
{ | |||
src->ops->blit(src, dst, dst_x, dst_y); | |||
return; | |||
} | |||
for(y = 0; y < src->ht; y++) | |||
for(x = 0; x < src->wd; x++) | |||
{ | |||
c = read_pixel(src, x, y); | |||
write_pixel(dst, dst_x + x, dst_y + y, c); | |||
} | |||
} | |||
/***************************************************************************** | |||
find 8x8 font in VGA BIOS ROM | |||
*****************************************************************************/ | |||
unsigned char FAR *bios_8x8_font(void) | |||
{ | |||
unsigned char FAR *font; | |||
regs_t regs; | |||
/* use BIOS INT 10h AX=1130h to find font #3 (8x8) in ROM */ | |||
memset(®s, 0, sizeof(regs)); /* for Watcom C */ | |||
regs.R_AX = 0x1130; | |||
regs.R_BX = 0x0300; | |||
trap(0x10, ®s); | |||
/* CauseWay DOS extender seems to return a selector in ES, | |||
instead of real-mode segment value (usu. 0xC000) */ | |||
#if defined(__WATCOMC__)&&defined(__386__) | |||
font = FARPTR(0xC000, regs.R_BP); | |||
#else | |||
font = FARPTR(regs.R_ES, regs.R_BP); | |||
#endif | |||
return font; | |||
} | |||
/***************************************************************************** | |||
*****************************************************************************/ | |||
void bputs(bmp_t *bmp, unsigned x, unsigned y, const char *s) | |||
{ | |||
unsigned char FAR *font; | |||
bmp_t src; | |||
font = bios_8x8_font(); | |||
src.wd = 8; | |||
src.ht = 8; | |||
src.ops = &g_ops1; | |||
for(; *s != '\0'; s++) | |||
{ | |||
src.raster = font + 8 * (*s); | |||
blit1(&src, bmp, x, y); | |||
x += 8; | |||
} | |||
} | |||
/*============================================================================ | |||
DEMO | |||
============================================================================*/ | |||
/***************************************************************************** | |||
*****************************************************************************/ | |||
static void border3d(bmp_t *bmp, int x, int y, unsigned wd, unsigned ht, | |||
char down) | |||
{ | |||
if(down) | |||
{ | |||
bmp->fore_color = 8; | |||
hline(bmp, x + 0, y + 0, wd - 1); | |||
vline(bmp, x + 0, y + 0, ht - 1); | |||
bmp->fore_color = 0; | |||
hline(bmp, x + 1, y + 1, wd - 3); | |||
vline(bmp, x + 1, y + 1, ht - 3); | |||
bmp->fore_color = 7; | |||
hline(bmp, x + 1, y + ht - 2, wd - 2); | |||
vline(bmp, x + wd - 2, y + 1, ht - 2); | |||
bmp->fore_color = 15; | |||
hline(bmp, x + 0, y + ht - 1, wd); | |||
vline(bmp, x + wd - 1, y + 0, ht); | |||
} | |||
else | |||
{ | |||
bmp->fore_color = 7; | |||
hline(bmp, x + 0, y + 0, wd - 1); | |||
vline(bmp, x + 0, y + 0, ht - 1); | |||
bmp->fore_color = 15; | |||
hline(bmp, x + 1, y + 1, wd - 3); | |||
vline(bmp, x + 1, y + 1, ht - 3); | |||
bmp->fore_color = 8; | |||
hline(bmp, x + 1, y + ht - 2, wd - 2); | |||
vline(bmp, x + wd - 2, y + 1, ht - 2); | |||
bmp->fore_color = 0; | |||
hline(bmp, x + 0, y + ht - 1, wd); | |||
vline(bmp, x + wd - 1, y + 0, ht); | |||
} | |||
} | |||
/***************************************************************************** | |||
*****************************************************************************/ | |||
static void demo(bmp_t *bmp, const char *title) | |||
{ | |||
unsigned x = 10, y = 10, wd = 180, ht = 50; | |||
/* erase screen to blue */ | |||
bmp->fore_color = 1; | |||
fill_rect(bmp, 0, 0, bmp->wd, bmp->ht); | |||
/* draw gray window with 3D border */ | |||
bmp->fore_color = 7; | |||
fill_rect(bmp, x, y, wd, ht); | |||
border3d(bmp, x, y, wd, ht, 0); | |||
/* draw white-on-green title bar */ | |||
bmp->fore_color = 2; | |||
fill_rect(bmp, x + 2, y + 2, wd - 4, 10); | |||
bmp->back_color = 2; | |||
bmp->fore_color = 15; | |||
bputs(bmp, x + 3, y + 3, title); | |||
/* draw menu bar on existing gray background */ | |||
bmp->back_color = 7; | |||
bmp->fore_color = 0; | |||
bputs(bmp, x + 3, y + 13, "File Edit"); | |||
/* draw white inner area with 3D border */ | |||
bmp->fore_color = 15; | |||
fill_rect(bmp, x + 3, y + 21, wd - 6, ht - 24); | |||
border3d(bmp, x + 3, y + 21, wd - 6, ht - 24, 1); | |||
/* await key pressed */ | |||
getch(); | |||
} | |||
/***************************************************************************** | |||
*****************************************************************************/ | |||
int main(void) | |||
{ | |||
static const unsigned wd[] = | |||
{ | |||
640, 320, 640, 320, 320 | |||
}; | |||
static const unsigned ht[] = | |||
{ | |||
480, 200, 480, 200, 200 | |||
}; | |||
static const ops_t *ops[] = | |||
{ | |||
&g_ops1, &g_ops2, &g_ops4p, &g_ops8, &g_ops8x | |||
}; | |||
static const unsigned mode[] = | |||
{ | |||
0x11, 5, 0x12, 0x13, 0x13 | |||
}; | |||
static const char *title[] = | |||
{ | |||
"640x480x2", "320x200x4", "640x480x16", "320x200x256", | |||
"320x200x256 ModeX" | |||
}; | |||
/**/ | |||
regs_t regs; | |||
unsigned i; | |||
bmp_t bmp; | |||
#if defined(__DJGPP__) | |||
if(!(_crt0_startup_flags & _CRT0_FLAG_NEARPTR)) | |||
{ | |||
if(!__djgpp_nearptr_enable()) | |||
{ | |||
printf("Could not enable nearptr access " | |||
"(Windows NT/2000/XP?)\n"); | |||
} | |||
} | |||
#endif | |||
for(i = 0; i < sizeof(wd) / sizeof(wd[0]); i++) | |||
{ | |||
bmp.raster = FARPTR(0xA000, 0); | |||
bmp.wd = wd[i]; | |||
bmp.ht = ht[i]; | |||
bmp.ops = ops[i]; | |||
memset(®s, 0, sizeof(regs)); /* for Watcom C */ | |||
regs.R_AX = mode[i]; | |||
trap(0x10, ®s); | |||
/* to make CGA graphics work like other graphics modes... */ | |||
if(mode[i] == 0x05) | |||
{ | |||
/* 1) turn off screwy CGA addressing */ | |||
outportb(VGA_CRTC_INDEX, 0x17); | |||
outportb(VGA_CRTC_DATA, inportb(VGA_CRTC_DATA) | 1); | |||
/* 2) turn off doublescan */ | |||
outportb(VGA_CRTC_INDEX, 9); | |||
outportb(VGA_CRTC_DATA, inportb(VGA_CRTC_DATA) & ~0x80); | |||
/* 3) move the framebuffer from B800:0000 to A000:0000 */ | |||
outportb(VGA_GC_INDEX, 6); | |||
outportb(VGA_GC_DATA, inportb(VGA_GC_INDEX) & ~0x0C); | |||
} | |||
/* to convert mode 13h to Mode X... */ | |||
else if(i == 4) | |||
{ | |||
/* 1) turn off Chain-4 addressing */ | |||
outportb(VGA_SEQ_INDEX, 0x04); | |||
outportb(VGA_SEQ_DATA, inportb(VGA_SEQ_DATA) & ~0x08); | |||
/* 2) turn off doubleword clocking */ | |||
outportb(VGA_CRTC_INDEX, 0x14); | |||
outportb(VGA_CRTC_DATA, inportb(VGA_CRTC_DATA) & ~0x40); | |||
/* 3) turn off word clocking in case it's on */ | |||
outportb(VGA_CRTC_INDEX, 0x17); | |||
outportb(VGA_CRTC_DATA, inportb(VGA_CRTC_DATA) | 0x40); | |||
} | |||
demo(&bmp, title[i]); | |||
} | |||
/* return to text mode */ | |||
memset(®s, 0, sizeof(regs)); /* for Watcom C */ | |||
regs.R_AX = 0x03; | |||
trap(0x10, ®s); | |||
return 0; | |||
} |
@ -1,235 +1,298 @@ | |||
BITS 16 | |||
;http://www.ousob.com/ng/bios/ng1223.php | |||
start: | |||
; Set up 4K stack after this bootloader | |||
; [Remember: Effective Address = Segment*16 + Offset] | |||
mov ax, 0x7C0 ; Set 'ax' equal to the location of this bootloader divided by 16 | |||
add ax, 0x20 ; Skip over the size of the bootloader divided by 16 | |||
mov ss, ax ; Set 'ss' to this location (the beginning of our stack region) | |||
mov sp, 8192 ; Set 'ss:sp' to the top of our 8K stack | |||
; Set data segment to where we're loaded so we can implicitly access all 64K from here | |||
mov ax, 0x7C0 ; Set 'ax' equal to the location of this bootloader divided by 16 | |||
mov ds, ax ; Set 'ds' to the this location | |||
mov [disk_identifier], dl | |||
; Print our message and stop execution | |||
mov si, message ; Put address of the null-terminated string to output into 'si' | |||
call print ; Call our string-printing routine | |||
mov si, enter_debug_mode | |||
call print | |||
call printCRLF | |||
; here goes wait call, for the user to enter debug mode. | |||
; Wating for 2 seconds: | |||
mov ah, 0x86 ; code for waiting interupt call | |||
mov cx, 0x001e ; high count of microseconds | |||
mov dx, 0x8480 ; low count | |||
int 0x15 | |||
.busy_wait_for_key: | |||
xor ax, ax | |||
mov ah, 0x01 ; BIOS call to wait for key | |||
int 0x16 | |||
jnz debug_mode | |||
; entering system check: | |||
mov si, enter_system_check | |||
mov si, sys_check_ok ; Put address of the null-terminated string to output into 'si' | |||
call print ; Call our string-printing routine | |||
mov si, boot_system ; Put address of the null-terminated string to output into 'si' | |||
call print ; Call our string-printing routine | |||
;This goes first as to now overwrite %ah and %al. | |||
mov ax, 0x0 | |||
mov es, ax ;Section to write into | |||
mov ah, 0x2 ;Read sectors from drive | |||
mov al, 0xf ;Number of sectors to read (15 * 512 = 7680 bytes) | |||
mov ch, 0x0 ;Low 8 bits of cylinder | |||
mov cl, 0x11 ;First sector to read (bits 0-5), upper bits of cylinder (bits 6-7) | |||
mov dh, 0x0 ;Head number | |||
mov dl, [disk_identifier] ;0x0 ;Drive number | |||
mov bx, 0x7e00 ;Offset into section | |||
int 0x13 ;Low level disk services | |||
;mov [0x7000], es ; saving retult of read | |||
; | |||
;Debug dump of loaded memory | |||
;mov si, 500 | |||
;mov cx, 512 | |||
;call b_dumpmem | |||
jnc notcarry | |||
mov si, error_str | |||
call print | |||
jmp endcarrycheck | |||
; | |||
notcarry: | |||
mov si, success_str | |||
call print | |||
call printCRLF | |||
call printCRLF | |||
; xor ax, ax | |||
; mov al, [disk_identifier] | |||
; call dumpax | |||
mov dl, [disk_identifier] | |||
mov ax, 0x7e0 | |||
mov ds, ax | |||
jmp 0x7e0:0x00 | |||
endcarrycheck: | |||
cli ; Clear the Interrupt Flag (disable external interrupts) | |||
hlt ; Halt the CPU (until the next external interrupt) | |||
debug_mode: | |||
mov si, .welcome_debug | |||
call print | |||
cli ; Clear the Interrupt Flag (disable external interrupts) | |||
hlt | |||
.welcome_debug db 'This is debug mode', 0 | |||
data: | |||
message db 'Bootloader for SingOS! v0.0.3',13,10,0 | |||
enter_debug_mode db 'Press d to enter bootloader debug mode',13,10,0 | |||
enter_system_check db 'Performing system check:',13,10,0 | |||
sys_check_ok db 'System check ok', 13, 10, 0 | |||
boot_system db 'Read SingOS from disk', 13, 10, 0 | |||
error_str db 'Error', 0 | |||
success_str db 'Success', 0 | |||
disk_identifier db 0 | |||
; Routine for printing a 'ax' as hex | |||
dumpax: | |||
pusha ; save registers | |||
mov bx, ax | |||
mov ah, 0xE ; Teletype output | |||
mov cx, 4 ; 4 nipples in a 16 bit word | |||
.loop: | |||
rol bx, 4 ; rotate to next nipple | |||
mov al, bl ; we copy to al because we need to mask only the low 4 bits | |||
and al, 1111b ; Do the masking | |||
add al, '0' ; convert to ASCII | |||
cmp al, '9' ; If we are greater than 9 ascii, we add 7 to make digit 10 be represented as 'A' | |||
jbe .skip ; -|- | |||
add al, 7 ; -|- | |||
.skip: ; -|- | |||
int 0x10 ; BIOS call 'output' | |||
loop .loop | |||
popa ; restore registers | |||
ret | |||
dumpax10: ; Prints ax as 16-bit decimal number | |||
pusha | |||
mov bx, 10 ; Divisor | |||
mov cx, 5 ; Loop 5 times | |||
.loop1: ; finds digits and pushes them to stack | |||
xor dx, dx | |||
div bx | |||
add dl, '0' | |||
push dx | |||
loop .loop1 | |||
%include "bootloader_macros.inc" | |||
%define STAGE1_BASE 0x7c00 | |||
%define STAGE2_BASE (STAGE1_BASE + 0x200) | |||
%define PROTECED_MODE_BASE (STAGE2_BASE + 0x200) | |||
%define GDT 0x0800 | |||
%define GDT_CodeSegIndex 1 | |||
%define GDT_DataSegIndex 2 | |||
%define GDT_CodeSegmentSelector GDT_Selector(GDT_CodeSegIndex, 0, 0) | |||
%define GDT_DataSegmentSelector GDT_Selector(GDT_DataSegIndex, 0, 0) | |||
%if 1; TEXT MODE | |||
%define VIDEO 0xB8000 | |||
%else | |||
%define VIDEO 0xA0000 | |||
%endif | |||
mov ah, 0xE | |||
mov cx, 5 ; Loop 5 times | |||
mov bl, '0' | |||
.loop2: ; Pops from stack until it hits a non-'0' value. It then jumps to nonzero_nopop to print it. | |||
pop dx | |||
mov al, dl | |||
cmp al, bl | |||
jne .nonzero_nopop | |||
loop .loop2 | |||
.nonzero_loop: ; Pops values from the stack and prints them. | |||
pop dx | |||
mov al, dl | |||
.nonzero_nopop: ; Part of the loop that prints the value. Jump to here to print without popping on first iteration. | |||
int 0x10 | |||
loop .nonzero_loop | |||
popa | |||
ret | |||
dumpax10_rev: ; Prints ax as 16-bit decimal number in reverse | |||
pusha | |||
mov cx, 10 ; Divisor | |||
.loop: | |||
xor dx, dx ; zero dx | |||
div cx ; Divide dx:ax by 10 -> quotient in ax, remainder in dx | |||
mov bx, ax ; save quotient in bx | |||
%define STACK_POINTER_MAX STAGE1_BASE-2 ; Stack grows downwards from right under stage_1 | |||
; /$$$$$$ /$$ /$$ | |||
; /$$__ $$ | $$ /$$$$ | |||
; | $$ \__//$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ |_ $$ | |||
; | $$$$$$|_ $$_/ |____ $$ /$$__ $$ /$$__ $$ | $$ | |||
; \____ $$ | $$ /$$$$$$$| $$ \ $$| $$$$$$$$ | $$ | |||
; /$$ \ $$ | $$ /$$ /$$__ $$| $$ | $$| $$_____/ | $$ | |||
; | $$$$$$/ | $$$$/| $$$$$$$| $$$$$$$| $$$$$$$ /$$$$$$ | |||
; \______/ \___/ \_______/ \____ $$ \_______//$$$$$$|______/ | |||
; /$$ \ $$ |______/ | |||
; | $$$$$$/ | |||
; \______/ | |||
segment Stage1 vstart=STAGE1_BASE | |||
Stage1: | |||
jmp short SkipWeirdBIOSShite | |||
nop ; Used later as a FLAG byte for extended INT 13 Disk Func.'s (See instruction at: 7CADh). | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
; Disk description table, to make it a valid floppy | |||
; Note: some of these values are hard-coded in the source! | |||
; Values are those used by IBM for 1.44 MB, 3.5" diskette | |||
; NOTE(jakob): From MikeOS | |||
; Why do we need this... damn BIOS | |||
; OEMLabel db "SingOs " ; Disk label | |||
%if 1 | |||
times 40-($-$$) db 0 | |||
%else | |||
BytesPerSector dw 512 ; Bytes per sector | |||
SectorsPerCluster db 1 ; Sectors per cluster | |||
ReservedForBoot dw 1 ; Reserved sectors for boot record | |||
NumberOfFats db 2 ; Number of copies of the FAT | |||
RootDirEntries dw 224 ; Number of entries in root dir | |||
; (224 * 32 = 7168 = 14 sectors to read) | |||
LogicalSectors dw 2880 ; Number of logical sectors | |||
MediumByte db 0xF0 ; Medium descriptor byte | |||
SectorsPerFat dw 9 ; Sectors per FAT | |||
SectorsPerTrack dw 18 ; Sectors per track (36/cylinder) | |||
Sides dw 2 ; Number of sides/heads | |||
HiddenSectors dd 0 ; Number of hidden sectors | |||
LargeSectors dd 0 ; Number of LBA sectors | |||
DriveNo dw 0 ; Drive No: 0 | |||
Signature db 0 ; Drive signature: 41 for floppy | |||
VolumeID dd 0x00000000 ; Volume ID: any number | |||
VolumeLabel db "SingOs "; Volume Label: any 11 chars | |||
FileSystem db "VSFS " ; File system type: don't change! | |||
%endif | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
SkipWeirdBIOSShite: | |||
cli ; Disable interrupts | |||
; Setup segments | |||
jmp 0x0000:CanonicalBootloaderStart ; CS:IP = 0x0000:7Cxx where xx is | |||
; the size of the BPB + instructions | |||
; before CanonicalBootloaderStart | |||
CanonicalBootloaderStart: | |||
xor ax, ax | |||
mov ds, ax | |||
mov es, ax | |||
mov fs, ax | |||
mov ss, ax | |||
; Setup stack | |||
mov sp, STACK_POINTER_MAX | |||
sti ; Enable interrupts | |||
cld | |||
mov [BootDriveNumber], dl ; Save boot device number | |||
mov eax, 0 ; Needed for some older BIOSes | |||
mov si, FirstStageString | |||
call PrintString | |||
mov cx, 5 ; Try five times | |||
mov al, dl ; put remainder in al | |||
add al, '0' ; Make ASCII | |||
.TryReadLoop: | |||
xor ax, ax ; Reset disk controller | |||
mov es, ax ; Just to be damn sure! (Still canonical 0 segment) | |||
movzx dx, byte [BootDriveNumber]; | |||
int 0x13 | |||
mov ah, 0xE ; Set teletype output | |||
int 0x10 ; BIOS: write one char | |||
mov ax, 0x0202 ; Read one sector | |||
mov cx, 0x0002 ; Cylinder 0, sector 2 | |||
movzx dx, byte [BootDriveNumber] ; Head zero, drive number | |||
mov bx, STAGE2_BASE ; Where we put the second stage | |||
int 0x13 | |||
jnc .BreakTryReadLoop | |||
loop .TryReadLoop | |||
jmp DiskReadError | |||
.BreakTryReadLoop: | |||
jmp STAGE2_BASE | |||
DiskReadError: | |||
mov si, DiskReadErrorStr | |||
call PrintString | |||
xor ax, ax | |||
int 16h ; Wait for keystroke | |||
xor ax, ax | |||
int 19h ; Reboot the system | |||
jmp DiskReadError | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
%include "bootloader_bios_functions.inc" | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
FirstStageString: db "Loading stage 2...", 13, 10, 0 | |||
DiskReadErrorStr: db "Disk read error. Press any key to reboot.", 0 | |||
BootDriveNumber db 0 | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
times 512-($-$$)-2 db 0 ; Zero pad to boot signature | |||
db 0x55, 0xAA ; Boot signature | |||
; /$$$$$$ /$$ /$$$$$$ | |||
; /$$__ $$ | $$ /$$__ $$ | |||
; | $$ \__//$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ |__/ \ $$ | |||
; | $$$$$$|_ $$_/ |____ $$ /$$__ $$ /$$__ $$ /$$$$$$/ | |||
; \____ $$ | $$ /$$$$$$$| $$ \ $$| $$$$$$$$ /$$____/ | |||
; /$$ \ $$ | $$ /$$ /$$__ $$| $$ | $$| $$_____/ | $$ | |||
; | $$$$$$/ | $$$$/| $$$$$$$| $$$$$$$| $$$$$$$ | $$$$$$$$ | |||
; \______/ \___/ \_______/ \____ $$ \_______//$$$$$$|________/ | |||
; /$$ \ $$ |______/ | |||
; | $$$$$$/ | |||
; \______/ | |||
; org STAGE2_BASE | |||
segment Stage2 vstart=STAGE2_BASE | |||
Stage2: | |||
call PrintRealAddress | |||
CRLF | |||
mov si, SecondStageString | |||
call PrintString | |||
mov si, EnablingA20Str | |||
call PrintString | |||
mov ax, bx | |||
;test ax, ax | |||
cmp ax, 0 | |||
jnz .loop | |||
popa | |||
ret | |||
printCRLF: | |||
mov ah, 0xE | |||
mov al, 13 | |||
int 0x10 | |||
mov al, 10 | |||
int 0x10 | |||
ret | |||
; Routine for outputting string in 'si' register to screen | |||
print: | |||
mov ah, 0xE ; Specify 'int 0x10' 'teletype output' function | |||
; [AL = Character, BH = Page Number, BL = Colour (in graphics mode)] | |||
.printchar: | |||
lodsb ; Load byte at address SI into AL, and increment SI | |||
cmp al, 0 | |||
je .done ; If the character is zero (NUL), stop writing the string | |||
int 0x10 ; Otherwise, print the character via 'int 0x10' | |||
jmp .printchar ; Repeat for the next character | |||
.done: | |||
ret | |||
; b_dumpmem: | |||
; push ax | |||
; push dx | |||
; call printCRLF | |||
; shr cx, 1 | |||
; xor dx, dx ; zero dx | |||
; .loop: | |||
; cmp dx, cx | |||
; jae .end | |||
; mov ax, word [esi + 2*edx] | |||
; call dumpax | |||
; mov ax, 0xe20 | |||
; int 0x10 | |||
; inc dx | |||
; jmp .loop | |||
; .end: | |||
; pop dx | |||
; pop ax | |||
; ret | |||
; Pad to 510 bytes (boot sector size minus 2) with 0s, and finish with the two-byte standard boot signature | |||
times 510-($-$$) db 0 | |||
dw 0xAA55 ; => 0x55 0xAA (little endian byte order) | |||
; bootloder debug_mode goes here | |||
times 8192-($-$$) db 0 | |||
; From Version 0.0.3 we are concatinate the bootloader and the kernel after compile time | |||
;%include "kernel.nasm" | |||
;times 8192-($-$$) db 0 | |||
call Enable_A20 | |||
mov al, '0' >> 1 | |||
call Check_A20 | |||
rcl al, 1 | |||
mov byte [A20Status.Bit], al | |||
mov si, A20Status | |||
call PrintString | |||
mov ax, 0x0003 ; AH=0 (Change video mode), AL=13h (Mode) = 320x200 - 256 colors | |||
mov bx, 0x0000 | |||
int 0x10 ; Video BIOS interrupt | |||
%if 0 ; VESA test (Totally wrong!!!! read up!) | |||
; mov ax, 0x4f02 ; VESA mode | |||
; mov bx, 0x0301 ; 132 cols by 60 rows | |||
; int 0x10 ; Video BIOS interrupt | |||
%endif | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
; Global Descriptor Table ; | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
%assign GDT_SIZE 0 | |||
GDT_NULL_ENTRY GDT | |||
%assign GDT_SIZE (GDT_SIZE+8) | |||
GDT_ENTRY (GDT + (GDT_CodeSegIndex*8)), 0x00000000, 0xffffffff, CodeRead, 0, 1 | |||
%assign GDT_SIZE (GDT_SIZE+8) | |||
GDT_ENTRY (GDT + (GDT_DataSegIndex*8)), 0x00000000, 0xffffffff, DataMutable, 0, 1 | |||
%assign GDT_SIZE (GDT_SIZE+8) | |||
cli | |||
lgdt [GDT_Record] | |||
mov eax, cr0 | |||
or al, 1 ; set PE (Protection Enable) bit in CR0 (Control Register 0) | |||
mov cr0, eax | |||
jmp ClearPrefetchQueue | |||
nop | |||
nop | |||
ClearPrefetchQueue: | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
;; Manually assembled long jump | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
db 0x66 ; 32bit override | |||
db 0xea ; Long jump | |||
dd PROTECED_MODE_BASE ; Absolute address | |||
dw GDT_CodeSegmentSelector ; Descriptor Selector | |||
; jmp GDT_CodeSegmentSelector:ProtectedModeBaby ; 8: is for the first descriptor in the GDT that is not the null-descriptor | |||
HALT | |||
GDT_Record: | |||
dw GDT_SIZE - 1 ; Size of GDT in bytes minus 1 | |||
dd GDT ; Linear address of GDT | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
%include "bootloader_A20.nasm" | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
SecondStageString: db "This is the second stage!", 13, 10, 0 | |||
EnablingA20Str: db "Enabling A20...", 13, 10, 0 | |||
A20Status: db "A20_Enabled=" | |||
.Bit: db '0', 13, 10, 0 | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
times 512-($-$$) db 0 | |||
BITS 32 | |||
segment ProtectedModeBaby vstart=PROTECED_MODE_BASE | |||
ProtectedModeBaby: | |||
; Code segment updated by the long jump here | |||
; Update Other Segments | |||
mov ax, GDT_DataSegmentSelector | |||
mov ds, ax | |||
mov ss, ax | |||
mov es, ax | |||
mov fs, ax | |||
mov gs, ax | |||
; Setup stack | |||
mov esp, 0xffffffff | |||
mov ecx, 0 | |||
mov edx, 0 | |||
lea edi, [VIDEO] | |||
mov ax, 0x4000 | |||
LoopRows: | |||
LoopCols: | |||
mov bl, cl | |||
xor bl, dl | |||
shl bl, 4 | |||
mov ah, bl | |||
ror bl, 1 | |||
xor ah, bl | |||
and ah, 0x70 | |||
mov al, dl | |||
add al, cl | |||
and al, 4 | |||
ror al, 1 | |||
or ah, al | |||
mov al, 0 | |||
mov WORD [edi], ax | |||
inc edi | |||
inc edi | |||
inc ecx | |||
cmp ecx, 80 | |||
je BreakLoopCols | |||
jmp LoopCols | |||
BreakLoopCols: | |||
mov ecx, 0 | |||
inc edx | |||
cmp edx, 25 | |||
je BreakLoopRows | |||
jmp LoopRows | |||
BreakLoopRows: | |||
WriteProtectedModeString: | |||
cld | |||
lea esi, [ProtectedWelcomeStr] | |||
lea edi, [VIDEO+(80*2)*12+19*2] | |||
.print_loop: | |||
mov al, BYTE [esi] | |||
test al, al | |||
jz .break_print_loop | |||
mov BYTE [edi], al | |||
mov BYTE [edi+1], 0x0f | |||
inc esi | |||
inc edi | |||
inc edi | |||
jmp .print_loop | |||
.break_print_loop: | |||
HALT | |||
;;;;;;;;;;;;;;;;;;;;;;;; | |||
;; Strings | |||
;;;;;;;;;;;;;;;;;;;;;;;; | |||
ProtectedWelcomeStr: db " Placeholder for SingOS - 32 bit edition! ", 0 |
@ -0,0 +1,106 @@ | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
Enable_A20: | |||
; Enables A20 gate using:the BIOS, keyboard controller, or Fast A20 | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
pushad ;Preserve registers | |||
pushfd ;Preserve EFLAGS because we might disable interrupts | |||
mov ax,0x2402 ;INT 15h AX=2402h: Query A20 status | |||
int 0x15 ;Check to see if A20 gate is enabled | |||
jc A20_No_BIOS ;Error? Don't use BIOS to enable gate | |||
test al,1 ;Test Bit 0 of AL | |||
je A20_Enabled ;A20 gate already enabled | |||
mov ax,0x2401 ;INT 15h AX=2401h: Enable A20 gate | |||
int 0x15 ;Use BIOS to enable A20 gate | |||
jc A20_No_BIOS ;Error? Don't use BIOS to enable gate | |||
or ah,ah ;Test AH | |||
jnz A20_No_BIOS ;Non-zero? A20 gate may not be enabled | |||
A20_Enabled: | |||
popfd ;Restore EFLAGS | |||
popad ;Restore registers | |||
ret ;Return | |||
A20_No_BIOS: | |||
mov ax,0x2403 ;INT 15h AX=2403h: Query A20 support | |||
int 0x15 ;Call BIOS to find out how the A20 gate can be enabled | |||
jc A20_KBD ;Error? Assume that keyboard controller is the only option | |||
test bx,1 ;Bit 0:Keyboard controller supported | |||
je A20_KBD ;BIOS indicates that keyboard controller is supported | |||
test bx,2 ;Bit 1:Fast A20 supported | |||
je FAST_A20 ;BIOS indicated that Fast A20 is supported | |||
call Check_A20 ;Test A20 gate manually | |||
jc A20_Enabled ;A20 gate already enabled | |||
A20_Fail: | |||
lea si,[A20_ERROR] ;"Unable to enable A20 gate!" | |||
call PrintString | |||
call A20_OUT_Wait ;Print string | |||
cli ;Disable interrupts | |||
hlt ;Halt machine | |||
FAST_A20: | |||
in al,0x92 ;Read System Control Port A | |||
test al,2 ;Test Fast A20 bit | |||
jnz A20_Fail ;Bit already set, failed to enable A20 gate | |||
or al,2 ;Set Bit 1:Enable Fast A20 | |||
and al,0xFE ;Always clear Bit 0 so that machine does not reboot | |||
out 0x92,al ;Write to port 92h | |||
call Check_A20 ;Check A20 gate | |||
jc A20_Enabled ;Success? | |||
cli ;No? something must have gone wrong | |||
hlt ;Clear interrupts and halt machine | |||
A20_KBD: | |||
cli ;Disable interrupts | |||
mov cx,50 ;Number of attempts to enable gate | |||
Use_KBD: | |||
call A20_OUT_Wait ;Wait for keyboard | |||
mov al,0xAD ;Disable Keyboard | |||
out 0x64,al ;Wait for Keyboard | |||
mov al,0xD0 ;Read Controller Output Port | |||
out 0x64,al | |||
call A20_IN_Wait ;Wait for Keyboard | |||
in al,0x60 ;Read Data Port | |||
push ax ;Save | |||
call A20_OUT_Wait ;Wait for Keyboard | |||
mov al,0xD1 ;Write Controller Output Port | |||
out 0x64,al | |||
call A20_OUT_Wait ;Wait for Keyboard | |||
pop ax ;Get port data back | |||
or al,10b ;Bit 1: Enable A20 gate | |||
out 0x60,al ;Write to data port | |||
call A20_OUT_Wait ;Wait for Keyboard | |||
mov al,0xAE ;Enable Keyboard | |||
out 0x64,al | |||
call A20_OUT_Wait ;Wait for Keyboard | |||
call Check_A20 ;Verify that gate is enabled | |||
jc A20_Enabled ;Yes? Return | |||
loop Use_KBD ;No? Keep trying | |||
jmp A20_Fail ;Could not enable gate after 50 tries | |||
A20_OUT_Wait: | |||
in al,0x64 ;Read status register | |||
test al,10b ;Is port ready? | |||
jnz A20_OUT_Wait ;Nope, wait | |||
ret ;Yep, continue | |||
A20_IN_Wait: | |||
in al,0x64 ;Read status register | |||
test al,1b ;Is port ready? | |||
jz A20_IN_Wait ;Nope, wait | |||
ret ;Yep, continue | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
Check_A20: | |||
; Test if A20 gate is enabled by comaparing the value in FFFF:7E0E | |||
; with the VBR boot signature at 0000:7DFE | |||
; Out: Carry flag set if A20 gate is enabled | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
pushad ;Preserve registers | |||
push es | |||
mov ax, 0xFFFF | |||
mov es, ax ;Extra segment:FFFF | |||
cmp WORD [es:0x7DFE + 16], 0xAAFF ;See if boot signature is wrapped at FFFF:7E0E (Meaning FFFF:7E0E = 0:7DFE) | |||
stc ; Assume we didn't wrap, yes A20 | |||
jne .End | |||
clc ; We did wrap, no A20 | |||
.End: | |||
pop es | |||
popad | |||
ret | |||
A20_ERROR db "Unable to enable A20 gate!",0 |
@ -0,0 +1,164 @@ | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
PrintString: | |||
; uses bios to print string | |||
; IN 'si': pointer to beginning of zero terminated string | |||
; OUT 'si': pointer to the zero terminator at the end of the string | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
pushf | |||
push ax | |||
cld ; Ensure direction flag is cleared (for LODSB) | |||
mov ah, 0xe | |||
.PrintLoop: | |||
lodsb | |||
test al, al | |||
jz .BreakPrintLoop | |||
int 0x10 | |||
jmp .PrintLoop | |||
.BreakPrintLoop: | |||
pop ax | |||
popf | |||
ret | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
PrintRealAddress: | |||
; Clobbers AX | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
mov ax, cs | |||
call PrintAx | |||
mov ax, 0xe00|':' | |||
int 0x10 | |||
pop ax | |||
push ax | |||
call PrintAx | |||
ret | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
PrintAx: | |||
PrintAxHex: | |||
; Prints the contens of ax as a hexadecimal number | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
pusha ; save registers | |||
mov dx, ax | |||
mov ah, 0xE ; Teletype output | |||
mov cx, 4 ; 4 nibbles in a 16 bit word | |||
.PrintLoop: | |||
rol dx, 4 ; rotate to next nibble | |||
mov al, dl ; we copy to al because we need to mask only the low 4 bits | |||
and al, 0xF ; Do the masking | |||
add al, '0' ; convert to ASCII | |||
; If we are greater than 9 ascii... | |||
cmp al, '9' | |||
jbe .SkipDiffToAsciiA | |||
add al, 'A'-('9'+1) ; ...add 7 to make digits 10 to 15 be represented as 'A' to 'F' | |||
.SkipDiffToAsciiA: | |||
int 0x10 ; BIOS call 'output' | |||
loop .PrintLoop | |||
popa ; restore registers | |||
ret | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
PrintAxDec: | |||
; Prints the contens of ax as a decimal number | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
pusha | |||
xor cx, cx ; Digit count starts at 0 | |||
test ax, ax | |||
jz .AlreadyZero | |||
mov bx, 10 ; Divisor | |||
.LoopDivide: ; finds digits and pushes them to stack | |||
test ax, ax | |||
jz .BreakLoopDivide | |||
xor dx, dx | |||
div bx ; dx = (dx:ax)%bx, ax = (dx:ax)/bx | |||
push dx | |||
inc cx ; Increase digit count | |||
jmp .LoopDivide | |||
.BreakLoopDivide: | |||
.LoopPrint: | |||
test cx, cx | |||
jz .BreakLoopPrint | |||
dec cx | |||
pop ax | |||
.AlreadyZero: | |||
add al, '0' ; Convert to ascii | |||
mov ah, 0xE | |||
int 0x10 | |||
jmp .LoopPrint | |||
.BreakLoopPrint: | |||
popa | |||
ret | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
PrintAxBin: | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
push ax | |||
push bx | |||
push cx | |||
xchg bx, ax | |||
bsr cx, bx | |||
inc cx | |||
ror bx, cl | |||
mov ah, 0xe | |||
.loop: | |||
mov al, '0'>>1 | |||
shl bx, 1 | |||
rcl al, 1 | |||
int 0x10 | |||
loop .loop | |||
pop cx | |||
pop bx | |||
pop ax | |||
ret | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
PrintMemoryRegion: | |||
; IN: DS:SI is the address to read from | |||
; IN: CX is the amount of 16 bit words to read | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
push cx | |||
push ax | |||
.Loop: | |||
lodsw | |||
call PrintAx | |||
loop .Loop | |||
pop ax | |||
pop cx | |||
ret | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
LoadOneSector: | |||
; Tries to load one sector to linear address ES:BX | |||
; IN: | |||
; Assumes CS == DS == SS | |||
; NOTE: No error checking on the track number | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
; C = LBA / (HeadsPerCylinder * SectorsPerTrack) | |||
; H = (LBA / SectorsPerTrack) mod HeadsPerCylinder | |||
; S = (LBA % SectorsPerTrack) + 1 | |||
mov cx, 5 ; Try five times | |||
.Retry: | |||
xor ax, ax ; Reset disk controller | |||
movzx dx, byte [BootDriveNumber]; | |||
int 0x13 | |||
mov ax, 0x0201 ; Read one sector | |||
mov cx, 0x0002 ; Cylinder 0, sector 2 | |||
movzx dx, byte [BootDriveNumber] ; Head zero, drive number | |||
int 0x13 | |||
jnc .BreakRetryLoop | |||
loop .Retry | |||
.BreakRetryLoop: | |||
ret |
@ -0,0 +1,64 @@ | |||
%macro HALT 0 | |||
%%h: | |||
cli | |||
hlt | |||
jmp %%h | |||
%endmacro | |||
%macro CRLF 0 | |||
push ax | |||
mov ax, 0xe00|13 | |||
int 0x10 | |||
mov al, 10 | |||
int 0x10 | |||
pop ax | |||
%endmacro | |||
; GDT Stuff | |||
%define Data 0000b | |||
%define DataMutable 0010b | |||
%define DataShrink 0100b | |||
%define DataShrinkMutable 0110b | |||
%define Code 1000b | |||
%define CodeRead 1010b | |||
%define CodeOnlyOwnPriv 1100b | |||
%define CodeOnlyOwnPrivRead 1110b | |||
%macro GDT_NULL_ENTRY 1 ; address | |||
%assign address %1 | |||
lea di, [address] | |||
xor ax, ax | |||
mov cx, 4 | |||
rep stosw | |||
%endmacro | |||
%macro GDT_ENTRY 6 ; address base limit type privilege bits32 | |||
%assign address %1 | |||
%assign base %2 | |||
%assign limit %3 | |||
%assign type (%4 & 0xf) | |||
%assign reserved (1<<4) | |||
%assign privilege ((%5 & 0x3) << 5) | |||
%assign present (1<<7) | |||
%assign access (present | privilege | reserved | type) | |||
%assign bits32 ((%6 & 1) << 2) | |||
%assign granularity (1<<3) | |||
%assign flags (granularity | bits32) | |||
%assign limit_0_15 (limit & 0xffff) | |||
%assign limit_16_19 ((limit >> 16) & 0xf) | |||
%assign base_0_15 (base & 0xffff) | |||
%assign base_16_23 ((base >> 16) & 0xff) | |||
%assign base_24_31 ((base >> 24) & 0xff) | |||
mov WORD [address + 0], limit_0_15 | |||
mov WORD [address + 2], base_0_15 | |||
mov WORD [address + 4], base_16_23 | (access << 8) | |||
mov WORD [address + 6], limit_16_19 | (flags << 4) | (base_24_31 << 8) | |||
%endmacro | |||
%define GDT_Selector(DescriptorIndex, TableIndicator, RequestorPrivLevel) ((DescriptorIndex << 3) | ((TableIndicator & 1) << 2) | (RequestorPrivLevel & 0x3)) |
@ -1,17 +1,19 @@ | |||
#!/usr/bin/bash | |||
if [ "$1" == "build" ] || [ "$1" == "run" ]; then | |||
nasm -fbin bootloader.nasm -o bootloader.bin | |||
nasm -fbin kernel.nasm -o kernel.bin | |||
cat bootloader.bin kernel.bin > SingOS.img | |||
if [ $1 == "run" ]; then | |||
#qemu-system-x86_64 -drive format=raw,file=SingOS.img | |||
#qemu-system-x86_64 -hda SingOS.img | |||
qemu-system-x86_64 -drive index=0,if=floppy,format=raw,file=SingOS.img | |||
else | |||
bash -c "echo;echo;echo 'Press [ENTER] to exit'; read line" | |||
fi | |||
fi | |||
AsmFile=bootloader.nasm | |||
# AsmFile=write_self.nasm | |||
echo "Done" | |||
BuildSteps=( | |||
"nasm ${AsmFile} -f bin -o boot.bin" | |||
"dd bs=512 count=2880 if=/dev/zero of=./Floppy.img" | |||
"dd conv=notrunc if=./boot.bin of=./Floppy.img" | |||
# "gcc -O0 -o ./VGA/grdemo.o ./VGA/grdemo.c" | |||
# "objcopy -O binary ./VGA/grdemo.o ./grdemo.bin" | |||
"qemu-system-x86_64 -vga cirrus -drive format=raw,file=Floppy.img" | |||
# "bochs" | |||
) | |||
for cmd in "${BuildSteps[@]}"; do | |||
echo -e "\033[1;34m${cmd}\033[0m" | |||
if ! eval $cmd ; then read line ; break; fi | |||
done |
@ -1,16 +0,0 @@ | |||
#!/bin/bash | |||
if [ "$1" != "run" ]; then | |||
nasm -fbin bootloader.nasm -o bootloader.bin | |||
nasm -fbin kernel.nasm -o kernel.bin | |||
cat bootloader.bin kernel.bin > SingOS.img | |||
fi | |||
if [ "$1" != "make" ]; then | |||
#qemu-system-x86_64 -drive format=raw,file=SingOS.img | |||
#qemu-system-x86_64 -hda SingOS.img | |||
qemu-system-x86_64 -drive index=0,if=floppy,format=raw,file=SingOS.img | |||
fi | |||
echo "Done" | |||
@ -0,0 +1,26 @@ | |||
# bx_enh_dbg_ini | |||
SeeReg[0] = TRUE | |||
SeeReg[1] = TRUE | |||
SeeReg[2] = TRUE | |||
SeeReg[3] = TRUE | |||
SeeReg[4] = FALSE | |||
SeeReg[5] = FALSE | |||
SeeReg[6] = FALSE | |||
SeeReg[7] = FALSE | |||
SingleCPU = FALSE | |||
ShowIOWindows = TRUE | |||
ShowButtons = TRUE | |||
SeeRegColors = TRUE | |||
ignoreNxtT = TRUE | |||
ignSSDisasm = TRUE | |||
UprCase = 0 | |||
DumpInAsciiMode = 3 | |||
isLittleEndian = TRUE | |||
DefaultAsmLines = 512 | |||
DumpWSIndex = 1 | |||
DockOrder = 0x132 | |||
ListWidthPix[0] = 127 | |||
ListWidthPix[1] = 95 | |||
ListWidthPix[2] = 172 | |||
MainWindow = 800, -2, 398, 878 | |||
FontName = Normal |
@ -0,0 +1,114 @@ | |||
[bits 16] | |||
[org 0x0600] | |||
%define STAGE1_BASE 0x7c00 | |||
%define STAGE2_BASE 0x0600 | |||
%define STACK_POINTER_MAX 0x2000 | |||
%macro HALT 0 | |||
%%h: | |||
cli | |||
hlt | |||
jmp %%h | |||
%endmacro | |||
%macro CRLF 0 | |||
push ax | |||
mov ax, 0xe00|13 | |||
int 0x10 | |||
mov al, 10 | |||
int 0x10 | |||
pop ax | |||
%endmacro | |||
segment Stage1 vstart=STAGE1_BASE | |||
Stage1: | |||
; Setup segments | |||
cli | |||
xor ax, ax | |||
xor bx, bx | |||
xor cx, cx | |||
xor dx, dx | |||
xor si, si | |||
xor di, di | |||
times 32-($-$$) nop | |||
times 7 inc ax | |||
times 40 nop | |||
call PrintAxHex | |||
call PrintCRLF | |||
HALT | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
PrintAx: | |||
PrintAxHex: | |||
; Prints the contens of ax as a hexadecimal number | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
pusha ; save registers | |||
mov dx, ax | |||
mov ah, 0xE ; Teletype output | |||
mov cx, 4 ; 4 nibbles in a 16 bit word | |||
.PrintLoop: | |||
rol dx, 4 ; rotate to next nibble | |||
mov al, dl ; we copy to al because we need to mask only the low 4 bits | |||
and al, 0xF ; Do the masking | |||
add al, '0' ; convert to ASCII | |||
; If we are greater than 9 ascii... | |||
cmp al, '9' | |||
jbe .SkipDiffToAsciiA | |||
add al, 'A'-('9'+1) ; ...add 7 to make digits 10 to 15 be represented as 'A' to 'F' | |||
.SkipDiffToAsciiA: | |||
int 0x10 ; BIOS call 'output' | |||
loop .PrintLoop | |||
popa ; restore registers | |||
ret | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
PrintAxDec: | |||
; Prints the contens of ax as a decimal number | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
pusha | |||
mov bx, 10 ; Divisor | |||
xor cx, cx ; Digit count starts at 0 | |||
.LoopDivide: ; finds digits and pushes them to stack | |||
test ax, ax | |||
jz .BreakLoopDivide | |||
xor dx, dx | |||
div bx ; dx = (dx:ax)%bx, ax = (dx:ax)/bx | |||
push dx | |||
inc cx ; Increase digit count | |||
jmp .LoopDivide | |||
.BreakLoopDivide: | |||
.LoopPrint: | |||
pop ax | |||
add al, '0' ; Convert to ascii | |||
mov ah, 0xE | |||
int 0x10 | |||
loop .LoopPrint | |||
popa | |||
ret | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
PrintCRLF: | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
pusha | |||
mov ah, 0xE | |||
mov al, 13 | |||
int 0x10 | |||
mov al, 10 | |||
int 0x10 | |||
popa | |||
ret | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
times 510-($-$$) db 0 ; Zero-pad to boot signature | |||
db 0x55, 0xAA ; Boot signature |
@ -0,0 +1,280 @@ | |||
%define GDT 0xfe00 | |||
%define GDT_CodeSegIndex 1 | |||
%define GDT_DataSegIndex 2 | |||
%define GDT_Selector(DescriptorIndex, TableIndicator, RequestorPrivLevel) ((DescriptorIndex << 3) | ((TableIndicator & 1) << 2) | (RequestorPrivLevel & 0x3)) | |||
%define GDT_CodeSegmentSelector GDT_Selector(GDT_CodeSegIndex, 0, 0) | |||
%define GDT_DataSegmentSelector GDT_Selector(GDT_DataSegIndex, 0, 0) | |||
; GDT Stuff | |||
%define Data 0000b | |||
%define DataMutable 0010b | |||
%define DataShrink 0100b | |||
%define DataShrinkMutable 0110b | |||
%define Code 1000b | |||
%define CodeRead 1010b | |||
%define CodeOwnRing 1100b | |||
%define CodeOwnRingRead 1110b | |||
%macro GDT_NULL_ENTRY 1 ; address | |||
%assign address %1 | |||
lea di, [address] | |||
xor ax, ax | |||
mov cx, 4 | |||
rep stosw | |||
%endmacro | |||
%macro GDT_ENTRY 6 ; address base limit type privilege bits32 | |||
%assign address %1 | |||
%assign base %2 | |||
%assign limit %3 | |||
%assign type (%4 & 0xf) | |||
%assign reserved (1<<4) | |||
%assign privilege ((%5 & 0x3) << 5) | |||
%assign present (1<<7) | |||
%assign access (present | privilege | reserved | type) | |||
%assign bits32 ((%6 & 1) << 2) | |||
%assign granularity (1<<3) | |||
%assign flags (granularity | bits32) | |||
%assign limit_0_15 (limit & 0xffff) | |||
%assign limit_16_19 ((limit >> 16) & 0xf) | |||
%assign base_0_15 (base & 0xffff) | |||
%assign base_16_23 ((base >> 16) & 0xff) | |||
%assign base_24_31 ((base >> 24) & 0xff) | |||
mov WORD [address + 0], limit_0_15 | |||
mov WORD [address + 2], base_0_15 | |||
mov WORD [address + 4], base_16_23 | (access << 8) | |||
mov WORD [address + 6], limit_16_19 | (flags << 4) | (base_24_31 << 8) | |||
%endmacro | |||
Go32Bit: | |||
;;;;;;;;;;;;;;;;;;; | |||
; Enable A20 line ; | |||
;;;;;;;;;;;;;;;;;;; | |||
call Enable_A20 | |||
; Set screen mode | |||
mov ax, 0x0003 ; AH=0 (Change video mode), AL=13h (Mode) = 320x200 - 256 colors | |||
mov bx, 0x0000 | |||
int 0x10 ; Video BIOS interrupt | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
; Global Descriptor Table ; | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
%assign GDT_SIZE 0 | |||
GDT_NULL_ENTRY GDT | |||
%assign GDT_SIZE (GDT_SIZE+8) | |||
GDT_ENTRY (GDT + (GDT_CodeSegIndex*8)), 0x00000000, 0xffffffff, CodeRead, 0, 1 | |||
%assign GDT_SIZE (GDT_SIZE+8) | |||
GDT_ENTRY (GDT + (GDT_DataSegIndex*8)), 0x00000000, 0xffffffff, DataMutable, 0, 1 | |||
%assign GDT_SIZE (GDT_SIZE+8) | |||
cli | |||
lgdt [GDT_Record] | |||
mov eax, cr0 | |||
or al, 1 ; set PE (Protection Enable) bit in CR0 (Control Register 0) | |||
mov cr0, eax | |||
jmp ClearPrefetchQueue | |||
nop | |||
nop | |||
ClearPrefetchQueue: | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
;; Manually assembled long jump ;; | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
db 0x66 ; 32bit override | |||
db 0xea ; Long jump | |||
dd PROTECED_MODE_BASE ; Absolute address | |||
dw GDT_CodeSegmentSelector ; Descriptor Selector | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
Enable_A20: | |||
; Enables A20 gate using:the BIOS, keyboard controller, or Fast A20 | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
pushad ;Preserve registers | |||
pushfd ;Preserve EFLAGS because we might disable interrupts | |||
mov ax,0x2402 ;INT 15h AX=2402h: Query A20 status | |||
int 0x15 ;Check to see if A20 gate is enabled | |||
jc A20_No_BIOS ;Error? Don't use BIOS to enable gate | |||
test al,1 ;Test Bit 0 of AL | |||
je A20_Enabled ;A20 gate already enabled | |||
mov ax,0x2401 ;INT 15h AX=2401h: Enable A20 gate | |||
int 0x15 ;Use BIOS to enable A20 gate | |||
jc A20_No_BIOS ;Error? Don't use BIOS to enable gate | |||
or ah,ah ;Test AH | |||
jnz A20_No_BIOS ;Non-zero? A20 gate may not be enabled | |||
A20_Enabled: | |||
popfd ;Restore EFLAGS | |||
popad ;Restore registers | |||
ret ;Return | |||
A20_No_BIOS: | |||
mov ax,0x2403 ;INT 15h AX=2403h: Query A20 support | |||
int 0x15 ;Call BIOS to find out how the A20 gate can be enabled | |||
jc A20_KBD ;Error? Assume that keyboard controller is the only option | |||
test bx,1 ;Bit 0:Keyboard controller supported | |||
je A20_KBD ;BIOS indicates that keyboard controller is supported | |||
test bx,2 ;Bit 1:Fast A20 supported | |||
je FAST_A20 ;BIOS indicated that Fast A20 is supported | |||
call Check_A20 ;Test A20 gate manually | |||
jc A20_Enabled ;A20 gate already enabled | |||
A20_Fail: | |||
lea si,[A20_ERROR] ;"Unable to enable A20 gate!" | |||
call PrintString | |||
call A20_OUT_Wait ;Print string | |||
cli ;Disable interrupts | |||
hlt ;Halt machine | |||
FAST_A20: | |||
in al,0x92 ;Read System Control Port A | |||
test al,2 ;Test Fast A20 bit | |||
jnz A20_Fail ;Bit already set, failed to enable A20 gate | |||
or al,2 ;Set Bit 1:Enable Fast A20 | |||
and al,0xFE ;Always clear Bit 0 so that machine does not reboot | |||
out 0x92,al ;Write to port 92h | |||
call Check_A20 ;Check A20 gate | |||
jc A20_Enabled ;Success? | |||
cli ;No? something must have gone wrong | |||
hlt ;Clear interrupts and halt machine | |||
A20_KBD: | |||
cli ;Disable interrupts | |||
mov cx,50 ;Number of attempts to enable gate | |||
Use_KBD: | |||
call A20_OUT_Wait ;Wait for keyboard | |||
mov al,0xAD ;Disable Keyboard | |||
out 0x64,al ;Wait for Keyboard | |||
mov al,0xD0 ;Read Controller Output Port | |||
out 0x64,al | |||
call A20_IN_Wait ;Wait for Keyboard | |||
in al,0x60 ;Read Data Port | |||
push ax ;Save | |||
call A20_OUT_Wait ;Wait for Keyboard | |||
mov al,0xD1 ;Write Controller Output Port | |||
out 0x64,al | |||
call A20_OUT_Wait ;Wait for Keyboard | |||
pop ax ;Get port data back | |||
or al,10b ;Bit 1: Enable A20 gate | |||
out 0x60,al ;Write to data port | |||
call A20_OUT_Wait ;Wait for Keyboard | |||
mov al,0xAE ;Enable Keyboard | |||
out 0x64,al | |||
call A20_OUT_Wait ;Wait for Keyboard | |||
call Check_A20 ;Verify that gate is enabled | |||
jc A20_Enabled ;Yes? Return | |||
loop Use_KBD ;No? Keep trying | |||
jmp A20_Fail ;Could not enable gate after 50 tries | |||
A20_OUT_Wait: | |||
in al,0x64 ;Read status register | |||
test al,10b ;Is port ready? | |||
jnz A20_OUT_Wait ;Nope, wait | |||
ret ;Yep, continue | |||
A20_IN_Wait: | |||
in al,0x64 ;Read status register | |||
test al,1b ;Is port ready? | |||
jz A20_IN_Wait ;Nope, wait | |||
ret ;Yep, continue | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
Check_A20: | |||
; Test if A20 gate is enabled by comaparing the value in FFFF:7E0E | |||
; with the VBR boot signature at 0000:7DFE | |||
; Out: Carry flag set if A20 gate is enabled | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
pushad ;Preserve registers | |||
push es | |||
mov ax, 0xFFFF | |||
mov es, ax ;Extra segment:FFFF | |||
cmp WORD [es:0x7DFE + 16], 0xAAFF ;See if boot signature is wrapped at FFFF:7E0E (Meaning FFFF:7E0E = 0:7DFE) | |||
stc ; Assume we didn't wrap, yes A20 | |||
jne .End | |||
clc ; We did wrap, no A20 | |||
.End: | |||
pop es | |||
popad | |||
ret | |||
A20_ERROR db "Unable to enable A20 gate!",0 | |||
times 512-($-$$) db 0 | |||
BITS 32 | |||
segment ProtectedModeBaby vstart=PROTECED_MODE_BASE | |||
ProtectedModeBaby: | |||
; Code segment updated by the long jump here | |||
; Update Other Segments | |||
mov ax, GDT_DataSegmentSelector | |||
mov ds, ax | |||
mov ss, ax | |||
mov es, ax | |||
mov fs, ax | |||
mov gs, ax | |||
; Setup stack | |||
mov esp, 0xffffffff | |||
mov ecx, 0 | |||
mov edx, 0 | |||
lea edi, [VIDEO] | |||
mov ax, 0x4000 | |||
LoopRows: | |||
LoopCols: | |||
mov bl, cl | |||
xor bl, dl | |||
shl bl, 4 | |||
mov ah, bl | |||
ror bl, 1 | |||
xor ah, bl | |||
and ah, 0x70 | |||
mov al, dl | |||
add al, cl | |||
and al, 4 | |||
ror al, 1 | |||
or ah, al | |||
mov al, 0 | |||
mov WORD [edi], ax | |||
inc edi | |||
inc edi | |||
inc ecx | |||
cmp ecx, 80 | |||
je BreakLoopCols | |||
jmp LoopCols | |||
BreakLoopCols: | |||
mov ecx, 0 | |||
inc edx | |||
cmp edx, 25 | |||
je BreakLoopRows | |||
jmp LoopRows | |||
BreakLoopRows: | |||
WriteProtectedModeString: | |||
cld | |||
lea esi, [ProtectedWelcomeStr] | |||
lea edi, [VIDEO+(80*2)*12+19*2] | |||
.print_loop: | |||
mov al, BYTE [esi] | |||
test al, al | |||
jz .break_print_loop | |||
mov BYTE [edi], al | |||
mov BYTE [edi+1], 0x0f | |||
inc esi | |||
inc edi | |||
inc edi | |||
jmp .print_loop | |||
.break_print_loop: | |||
HALT | |||
;;;;;;;;;;;;;;;;;;;;;;;; | |||
;; Strings | |||
;;;;;;;;;;;;;;;;;;;;;;;; | |||
ProtectedWelcomeStr: db " Placeholder for SingOS - 32 bit edition! ", 0 |
@ -1,305 +0,0 @@ | |||
BITS 16 | |||
start_sing: | |||
; loading essentials for SingOS to run | |||
; VSFS is loaded: | |||
mov [global_disk_identifier], dl ; saving disk_identifier, this is the number the disk that we are booting from. | |||
; This number is set by the bios | |||
jmp sing_ready | |||
%include "mem_lib/mem_lib.nasm" | |||
%include "lib/os_lib.nasm" | |||
%include "lib/string.nasm" | |||
%include "lib/debug_tools.nasm" | |||
%include "lib/std_power.nasm" | |||
%include "lib/svim.nasm" | |||
%include "vsfs/vsfs.nasm" | |||
%include "CLI/CLI.nasm" | |||
sing_ready: ; SingOS is ready for the user: | |||
call os_clear_screen | |||
mov si, welcome ; Put address of the null-terminated string to output into 'si' | |||
call print ; Call our string-printing routine | |||
print_format example_format_string, 0xdead, 0xbeef, 0xbabe, 420 | |||
call printCRLF | |||
call dump_general_registers | |||
call printCRLF | |||
call dump_segment_registers | |||
call printCRLF | |||
call dump_stack_registers | |||
call printCRLF | |||
call dump_status_flags | |||
call printCRLF | |||
call print_help_message | |||
; call dump_status_flags | |||
; call printCRLF | |||
mov si, command_line | |||
call print | |||
jmp terminal | |||
terminal: | |||
call wait_for_key | |||
jmp terminal | |||
wait_for_key: | |||
pusha | |||
mov ax, 0 | |||
mov ah, 0x10 ; BIOS call to wait for key | |||
int 0x16 | |||
cmp ax, 0x11b; ESC key | |||
je near .end | |||
cmp ax, 0x3b00 ; f1 key | |||
je .change_one | |||
cmp ax, 0x3c00 ; f2 key | |||
je .change_two | |||
cmp ax, 0x1c0d ; enter key | |||
je .enter_hit | |||
mov [.tmp_buf], ax ; save the key pressed befor printing it | |||
mov cx, [.tmp_buf] | |||
cmp cx, 0x0e08 ; backspace key | |||
;je .backspace_handler | |||
jne .dont_backspace | |||
call CLI_DELETE | |||
popa | |||
ret | |||
.dont_backspace: | |||
call CLI_ASCII_INPUT | |||
;mov ah, 0xE ; This destroy the high part of the key pressed | |||
;mov bl, 0x02 | |||
;int 0x10 | |||
;mov bx, [.os_command_buffer_counter] | |||
;cmp bx, 254 | |||
;je .os_buffer_full | |||
;mov ax, bx | |||
;add ax, .os_command_buffer | |||
;add bx, 0x01 | |||
;mov [.os_command_buffer_counter], bx | |||
;mov bx, ax | |||
;mov ax, [.tmp_buf] | |||
;mov [bx], ax | |||
.return_enter: | |||
mov ax, [.tmp_buf] | |||
popa ; But restore all other regs | |||
ret | |||
.os_buffer_full: | |||
mov si, .os_str_full | |||
call print | |||
popa | |||
ret | |||
.backspace_handler: | |||
; bx already set to the current buffer count | |||
mov bx, [.os_command_buffer_counter] | |||
cmp bx, 0x00 | |||
je .backspace_stop | |||
sub bx, 0x01 | |||
mov [.os_command_buffer_counter], bx | |||
add bx, .os_command_buffer | |||
mov ax, 0x00 | |||
mov [bx], ax | |||
mov ax, [.tmp_buf] ; load the backpace | |||
mov ah, 0xE ; print the backspace | |||
int 0x10 | |||
mov al, 0 | |||
int 0x10 | |||
mov al, 0x08 | |||
int 0x10 | |||
;mov al, 0x20 ; now the curser is one back | |||
;int 0x10 ; print null charecter | |||
.backspace_stop: | |||
popa ; But restore all other regs | |||
ret | |||
.change_one: | |||
mov al, 0x00 ; arg: index 0 | |||
call os_change_screen | |||
jmp terminal | |||
.change_two: | |||
mov al, 0x01 ; arg: index 0 | |||
call os_change_screen | |||
jmp terminal | |||
.enter_hit: | |||
call CLI_CONFIRM_INPUT | |||
jmp .command_interpreter | |||
.no_str: | |||
mov si, command_line | |||
call print | |||
jmp .return_enter | |||
.compare_with_LIST_searchindex dw 0 | |||
.compare_with_LIST_NAMES dw .compare_with_dumpmem, .compare_with_keyprint, .compare_with_display, .compare_with_svim, .compare_with_clear, .compare_with_ls, 0 | |||
.compare_with_LIST_POINTERS dw dumpmem, keyprint, .change_display, svim, .clearcommand, vsfs_list_files_command, 0 | |||
.compare_with_dumpmem db 'dumpmem', 0 | |||
.compare_with_keyprint db 'keyprint', 0 | |||
.compare_with_display db 'display', 0 ; original this is the display command for better grapichs | |||
.compare_with_svim db 'svim', 0 ; SingOS vim edition 'svim' | |||
.compare_with_clear db 'clear', 0 ; Clear the screen | |||
.compare_with_ls db 'ls', 0 ; List file table | |||
.end: | |||
mov si, exit_message | |||
call print | |||
call power_off | |||
cli | |||
hlt | |||
.change_display: | |||
mov ax, 0x4F02 ; set VBE mode | |||
mov bx, 0x4118 ; VBE mode number; notice that bits 0-13 contain the mode number and bit 14 (LFB) is set and bit 15 (DM) is clear. | |||
;xor bx, bx | |||
;xor cx, cx | |||
;xor dx, dx | |||
;mov ah, 0x06 | |||
;mov al, 0xff | |||
int 0x10 | |||
ret | |||
.clearcommand: | |||
xor bx, bx | |||
xor cx, cx ; Upper and left coordinate | |||
mov bh, 0x0f ; color for new screen 0 = black f = white | |||
mov dh, 0xff ; Select all screen | |||
mov dl, 0xff ; Select all screen | |||
mov ah, 0x07 ; scrool down | |||
mov al, 0x00 ; scrool 0 lines (means blank screen ) | |||
int 0x10 | |||
; move curser back to the top of the screen | |||
mov ah, 0x02 | |||
mov bh, 0x00 ; page number 0 | |||
mov dh, 0x00 ; row zero | |||
mov dl, 0x00 ; coloumn zero | |||
int 0x10 | |||
ret | |||
.tmp_buf dw 0 | |||
.os_command_buffer times 255 dw 0 | |||
.os_command_buffer_counter dw 0 | |||
.os_str_full db 13, 10, 'Buffer is full', 13, 10, 0 | |||
.command_interpreter: | |||
mov bx, [.os_command_buffer_counter] | |||
cmp bx, 0x00 | |||
je near .no_str ; First byte is 0 => No command | |||
call printCRLF | |||
add bx, .os_command_buffer ; Note addition. Sets bx to the end of the string, which should be guaranteed to be 0 | |||
mov ax, 0x00 | |||
mov [bx], ax ; Ensure that the command is null-terminated | |||
xor bx, bx | |||
mov [.os_command_buffer_counter], bx | |||
mov si, .os_command_buffer | |||
call print ; Echo the command | |||
lea si, [.os_command_buffer] | |||
;mov dword [.compare_with_LIST_searchindex], 0 ; Next time, start at 0 | |||
mov cx, 0 ; Index | |||
.command_interpreter_searchloop: | |||
;call printCRLF | |||
;mov ax, cx | |||
;call dumpax | |||
;mov bx, [.compare_with_LIST_searchindex] | |||
mov bx, cx | |||
add bx, bx ; The pointers are 2 bytes long. Compensate here | |||
;call printCRLF | |||
;mov ax, cx | |||
;call dumpax | |||
mov dx, [.compare_with_LIST_NAMES+bx] ; Here it HAS to be bx. Otherwise it is invalid for some reason | |||
mov bx, dx | |||
lea di, [bx] | |||
call stringcompare | |||
je .command_interpreter_foundcommand | |||
; I don't assume here that the registers contain the same values they used to after the calls | |||
;mov bx, [.compare_with_LIST_searchindex] | |||
;inc bx | |||
;mov [.compare_with_LIST_searchindex], bx | |||
inc cx | |||
mov bx, cx | |||
add bx, bx | |||
mov dx, [.compare_with_LIST_NAMES+bx] | |||
cmp dx, 0 ;Is it at the null terminator? | |||
jne .command_interpreter_searchloop ; There is another command to check | |||
jmp .no_str | |||
.command_interpreter_foundcommand: | |||
call printCRLF | |||
;mov bx, [.compare_with_LIST_searchindex] ; Remember this thing | |||
mov bx, cx | |||
add bx, bx ;The pointers are 2 bytes long. Compensate here | |||
;call printCRLF | |||
;mov ax, cx | |||
;call dumpax | |||
mov dx, [.compare_with_LIST_POINTERS+bx] ; This is where the program is. | |||
;mov ax, dx | |||
;call printCRLF | |||
;call dumpax | |||
call dx | |||
jmp .no_str | |||
; | |||
global_vars: | |||
global_vsfs_master_record dw 8 ; this is the index of the start of the master table for the filesystem | |||
; This should maby contain more information. | |||
; and somehow be setted in a fix sector, which holds all the variabels for SingOS | |||
; 8 is currently the magic number where the file system starts on our disk. | |||
global_vsfs_next_index dw 0 ; This is the next index to the next file created. | |||
; this var is set durling load of SingOS | |||
; Changed my mind, the index is currently loaded and written back to disk under | |||
; creation of a new file. | |||
global_disk_identifier db 0 ; set by the bios passed by the bootloader, | |||
; this is the bios ID | |||
data: | |||
welcome db "###############################################################################", 13, 10, "# Welcome to SingOS anniversary edition. #", 13, 10, "# This build marks 1 year of SingOS! #", 13, 10, "###############################################################################", 13, 10, 'Press ESC to halt.', 13, 10, 13, 10, 0 | |||
exit_message db 13, 10, 'Goodbye from SingOS',13,10,'The system has halted.', 0 | |||
command_line db 13, 10, 'groot@SingOS $ ', 0 | |||
number_one_zstring db '71', 0 | |||
example_format_string db "(%x-%x-%x){%d%%}",0 | |||
;times 131072-($-$$) db 0 ; 256 sectos | |||
;GLOBAL_VSFS_START db 'VSFS v0.1' ; sector 257 reserved for file system information | |||
times (1<<20)-($-$$) db 0 ; sector 258 to sector 2048 should be avaliable to the filesystem. |
@ -1 +0,0 @@ | |||
SingOs |
@ -1,2 +0,0 @@ | |||
Folder of compiling the OS | |||
This folder has to be empty on the repository |
@ -1,3 +0,0 @@ | |||
as sing_boot_alt.s -o ../compile_folder/alt.o | |||
ld -Ttext 0x7c00 --oformat=binary ../compile_folder/alt.o -o ../compile_folder/sing.bin | |||
dd if=../compile_folder/sing.bin of=../compile_folder/sing.img |
@ -1,3 +0,0 @@ | |||
as $1.s -o ../compile_folder/$2.o | |||
ld -Ttext 0x7c00 --oformat=binary ../compile_folder/$2.o -o ../compile_folder/$2.bin | |||
dd if=../compile_folder/$2.bin of=../compile_folder/$2.img |
@ -1,3 +0,0 @@ | |||
https://www.codeproject.com/Articles/664165/Writing-a-boot-loader-in-Assembly-and-C-Part | |||
http://www.computer-engineering.org/index.html // keyboard and mouse programming |
@ -1,76 +0,0 @@ | |||
#generate 16-bit code | |||
.code16 | |||
#hint the assembler that here is the executable code located | |||
.text | |||
.globl _start; | |||
#boot code entry | |||
_start: | |||
jmp _boot | |||
start: .asciz "Start.\n\r" | |||
error: .asciz "Error.\n\r" | |||
succes: .asciz "Succes.\n\r" | |||
ffs: .asciz "F.\n\r" | |||
end: .asciz "End.\n\r" | |||
.macro mWriteString str #macro which calls a function to print a string | |||
leaw \str, %si | |||
call .writeStringIn | |||
.endm | |||
# function to print the string | |||
.writeStringIn: | |||
lodsb | |||
orb %al, %al | |||
jz .writeStringOut | |||
movb $0x0e, %ah | |||
int $0x10 | |||
jmp .writeStringIn | |||
.writeStringOut: | |||
ret | |||
_boot: | |||
mWriteString start | |||
#This goes first as to now overwrite %ah and %al. | |||
mov $0x00, %ax | |||
mov %ax, %es #Section to write into | |||
mov $0x02, %ah # Read sectors from drive | |||
mov $0x01, %al # Number of sectors to read | |||
mov $0x00, %ch # Low 8 bits of cylinder | |||
mov $0x02, %cl # First sector to read (bits 0-5), upper bits of cylinder (bits 6-7) | |||
mov $0x00, %dh # Head number | |||
mov $0x00, %dl # Drive number | |||
# mov $0x00, %es | |||
mov $0xFF, %bx #Offset into section | |||
int $0x13 # Low level disk services | |||
jnc notcarry | |||
mWriteString error | |||
jmp endcarrycheck | |||
notcarry: | |||
mWriteString succes | |||
#fallthrough | |||
endcarrycheck: | |||
mWriteString mystr | |||
mWriteString end | |||
# | |||
#move to 510th byte from the start and append boot signature | |||
. = _start + 510 | |||
.byte 0x55 | |||
.byte 0xaa | |||
mystr: .asciz "asdf" | |||
. = _start + 1023 | |||
.byte 0x00 |
@ -1,227 +0,0 @@ | |||
#generate 16-bit code | |||
.code16 | |||
#hint the assembler that here is the executable code located | |||
.text | |||
.globl _start; | |||
#boot code entry | |||
_start: | |||
jmp _boot | |||
start: .asciz "Start.\n\r" | |||
error: .asciz "Error.\n\r" | |||
succes: .asciz "Succes.\n\r" | |||
ffs: .asciz "F.\n\r" | |||
end: .asciz "End.\n\r" | |||
derpy2str: .asciz "This is from derpy2.\n\r" | |||
cookies: .word derpy2 | |||
.macro mWriteString str #macro which calls a function to print a string | |||
leaw \str, %si | |||
call .writeStringIn | |||
.endm | |||
# function to print the string | |||
.writeStringIn: | |||
lodsb | |||
orb %al, %al | |||
jz .writeStringOut | |||
movb $0x0e, %ah | |||
int $0x10 | |||
jmp .writeStringIn | |||
.writeStringOut: | |||
ret | |||
_boot: | |||
mWriteString start | |||
movb $0x0e, %ah | |||
movb $'X', %al | |||
int $0x10 | |||
movb $'\n', %al | |||
int $0x10 | |||
movb $'\r', %al | |||
int $0x10 | |||
lgdt gdtdesc | |||
#movb $42, %bl #NOT 'A' | |||
#movb %bl, 0x512 | |||
#This goes first as to now overwrite %ah and %al. | |||
mov $0x00, %ax | |||
#mov $0x08, %ax | |||
mov %ax, %es #Section to write into | |||
mov $0x02, %ah # Read sectors from drive | |||
mov $0x01, %al # Number of sectors to read | |||
mov $0x00, %ch # Low 8 bits of cylinder | |||
mov $0x02, %cl # First sector to read (bits 0-5), upper bits of cylinder (bits 6-7) | |||
mov $0x00, %dh # Head number | |||
mov $0x00, %dl # Drive number | |||
# mov $0x00, %es | |||
#mov $0x7e00, %bx #Offset into section | |||
mov $(_start+0x200), %bx #Offset into section | |||
#mov $0x0, %bx #Offset into section | |||
int $0x13 # Low level disk services | |||
jnc notcarry | |||
#mWriteString error | |||
jmp endcarrycheck | |||
notcarry: | |||
#mWriteString succes | |||
#mov $0x7000, %ax | |||
#movb (%ax), %bl | |||
#movb %bl, ffs | |||
#movb 0x7000, %bl | |||
#movb %bl, ffs | |||
#mWriteString ffs | |||
#fallthrough | |||
endcarrycheck: | |||
#mWriteString mystr-block2_offset | |||
#mWriteString 0x513 | |||
#mWriteString mystr | |||
#ljmp $0x0, $derpy | |||
#.byte 0, 0, 0, 0, 0, 0, 0, 0 | |||
#ljmp $0x00, $0x7e00 | |||
#ljmp $0x00, $derpy2 | |||
ljmp $0x00, $code | |||
# movw $derpy, %ax | |||
# | |||
# cmp $0x7e00, %ax | |||
# je equal | |||
# mWriteString error | |||
# jmp after | |||
# | |||
# equal: | |||
# mWriteString succes | |||
# | |||
# after: | |||
/* | |||
movb $0x0e, %ah | |||
movw $derpy, %cx | |||
movb 0x0e, %ah | |||
movb $'I', %al | |||
int $0x10 | |||
movb 0x0e, %ah | |||
movb $'J', %al | |||
int $0x10 | |||
*/ | |||
#movw $0x7E00, %cx | |||
movw $derpy2, %cx | |||
movb $0x0e, %ah | |||
#movb $'Y', %al | |||
movb %ch, %al | |||
#movb $'H', %al | |||
#movb $0x7E, %al | |||
int $0x10 | |||
movb $0x0e, %ah | |||
#movb $'Z', %al | |||
movb %cl, %al | |||
#add $0x7E, %al | |||
#sub $0x50, %al | |||
#movb $0x3C, %al | |||
int $0x10 | |||
movb $0x0e, %ah | |||
movb $'\n', %al | |||
int $0x10 | |||
movb $0x0e, %ah | |||
movb $'\r', %al | |||
int $0x10 | |||
#mWriteString mystr | |||
#jmp derpy | |||
derpyret: | |||
mWriteString end | |||
#jmp 0x7008 | |||
#endend: | |||
#mWriteString end | |||
cli | |||
hlt | |||
# | |||
derpy: | |||
mWriteString ffs | |||
ljmp $0x00, $derpyret | |||
#jmp derpyret | |||
.p2align 2 /* force 4-byte alignment */ | |||
gdt: | |||
.word 0, 0 | |||
.byte 0, 0, 0, 0 | |||
/* code segment */ | |||
.word 0xFFFF, 0 | |||
.byte 0, 0x9A, 0xCF, 0 | |||
/* data segment */ | |||
.word 0xFFFF, 0 | |||
.byte 0, 0x92, 0xCF, 0 | |||
/* 16 bit real mode CS */ | |||
.word 0xFFFF, 0 | |||
.byte 0, 0x9E, 0, 0 | |||
/* 16 bit real mode DS */ | |||
.word 0xFFFF, 0 | |||
.byte 0, 0x92, 0, 0 | |||
/* this is the GDT descriptor */ | |||
gdtdesc: | |||
.word 0x27 /* limit */ | |||
.long gdt /* addr */ | |||
#move to 510th byte from the start and append boot signature | |||
. = _start + 510 | |||
.byte 0x55 | |||
.byte 0xaa | |||
#block2_offset: | |||
.byte 'A' #Byte 513 | |||
#mystr: .asciz "asdf\n\r" | |||
#derpderp: | |||
# mwriteString 0x7001 | |||
# jmp endend | |||
derpy2: | |||
mWriteString derpy2str | |||
ljmp $0x00, $derpyret | |||
code: | |||
mWriteString derpy2str | |||
movb $0x0e, %ah | |||
movb $'C', %al | |||
int $0x10 | |||
movb $0x0e, %ah | |||
movb $'\n', %al | |||
int $0x10 | |||
movb $0x0e, %ah | |||
movb $'\r', %al | |||
int $0x10 | |||
ljmp $0x00, $derpyret | |||
. = _start + 1021 | |||
.byte 0x00 | |||
.word derpy2 |
@ -1,120 +0,0 @@ | |||
#generate 16-bit code | |||
.code16 | |||
#hint the assembler that here is the executable code located | |||
.text | |||
.globl _start; | |||
#boot code entry | |||
_start: | |||
jmp _boot #jump to boot code | |||
welcome: .asciz "Hello, new World\n\r" #here we define the string | |||
enter_number: .asciz "Enter a number: \n\r" | |||
lower_msg: .asciz "\nYour number is to low :( \n\r" # 26 | |||
higher_msg: .asciz "\nYour number is to high :( \n\r" # 27 | |||
winner_msg: .asciz "\nYour are the CAMPION, :D \n\r" # 26 | |||
.macro mWriteString str #macro which calls a function to print a string | |||
leaw \str, %si | |||
call .writeStringIn | |||
.endm | |||
# function to print the string | |||
.writeStringIn: | |||
lodsb | |||
orb %al, %al | |||
jz .writeStringOut | |||
movb $0x0e, %ah | |||
int $0x10 | |||
jmp .writeStringIn | |||
.writeStringOut: | |||
ret | |||
.type get_number, @function | |||
get_number: | |||
# save state before function | |||
push %bp | |||
mov %sp, %bp | |||
push %bx | |||
push %cx | |||
# Start of function | |||
mWriteString enter_number | |||
mov $0, %ah | |||
mov $0, %al | |||
int $0x16 | |||
mov $0x0E, %ah | |||
int $0x10 | |||
pop %cx | |||
pop %bx | |||
mov %bp, %sp | |||
pop %bp | |||
ret | |||
.type string_to_int, @function | |||
string_to_int: | |||
/* Converts a string to an integer. Returns the integer in %rax. | |||
* %rax: Address of string to convert. | |||
*/ | |||
push %bp | |||
mov %sp, %bp | |||
push %bx | |||
push %cx | |||
mov %ax, %dx | |||
cmp $47, %dx | |||
jl not_a_num | |||
cmp $57, %dx | |||
jg not_a_num | |||
# I multiply by 10 to shift the number one placement to the right to add the newest integer. | |||
sub $48, %dx | |||
jmp convertdone # In ascii, numbers start at 0 = 48, 1 = 49, 2 = 50 and so on. So I subtract 48 to get the digit. | |||
not_a_num: | |||
xor %dx, %dx | |||
convertdone: | |||
pop %cx | |||
pop %bx | |||
mov %bp, %sp | |||
pop %bp | |||
ret | |||
_boot: | |||
mWriteString welcome | |||
guess: | |||
call get_number | |||
xor %ah, %ah | |||
call string_to_int | |||
cmp $5, %dx | |||
jl if_lower | |||
je if_eg | |||
jg if_higher | |||
if_lower: | |||
mWriteString lower_msg | |||
jmp guess | |||
if_higher: | |||
mWriteString higher_msg | |||
jmp guess | |||
if_eg: | |||
mWriteString winner_msg | |||
#move to 510th byte from the start and append boot signature | |||
. = _start + 510 | |||
.byte 0x55 | |||
.byte 0xaa |
@ -1,135 +0,0 @@ | |||
#generate 16-bit code | |||
.code16 | |||
#hint the assembler that here is the executable code located | |||
.text | |||
.globl _start; | |||
#boot code entry | |||
_start: | |||
welcome: .asciz "Welcome to this very fine Guessing game \n\r" #here we define the string | |||
enter_number: .asciz "Enter a number: \n" | |||
lower_msg: .asciz "Your number is to low :( \n" # 26 | |||
higher_msg: .asciz "Your number is to high :( \n" # 27 | |||
winner_msg: .asciz "Your are the CAMPION, :D \n" # 26 | |||
.macro mWriteString str #macro which calls a function to print a string | |||
leaw \str, %si | |||
call .writeStringIn | |||
.endm | |||
#jmp _boot | |||
# function to print the string | |||
.writeStringIn: | |||
lodsb | |||
orb %al, %al | |||
jz .writeStringOut | |||
movb $0x0e, %ah | |||
int $0x10 | |||
jmp .writeStringIn | |||
.writeStringOut: | |||
ret #jump to boot code | |||
mWriteString welcome | |||
/* | |||
guess: | |||
call get_number | |||
xor %ah, %ah | |||
call string_to_int | |||
cmp $5, %dx | |||
jl if_lower # rax less then 50 | |||
je if_eg | |||
jg if_higher | |||
if_lower: | |||
mWriteString lower_msg | |||
jmp guess | |||
if_higher: | |||
mWriteString higher_msg | |||
jmp guess | |||
if_eg: | |||
mWriteString winner_msg #message length | |||
hlt | |||
*/ | |||
#_boot: | |||
# mWriteString welcome | |||
#.type string_to_int, @function | |||
#string_to_int: | |||
/* Converts a string to an integer. Returns the integer in %rax. | |||
* %rax: Address of string to convert. | |||
*/ | |||
/* | |||
push %bp | |||
mov %sp, %bp | |||
push %bx | |||
push %cx | |||
mov %ax, %dx | |||
xor %ax, %ax | |||
cmp $47, %dx | |||
jl not_a_num | |||
cmp $57, %dx | |||
jg not_a_num | |||
# I multiply by 10 to shift the number one placement to the right to add the newest integer. | |||
sub $48, %dx # In ascii, numbers start at 0 = 48, 1 = 49, 2 = 50 and so on. So I subtract 48 to get the digit. | |||
not_a_num: | |||
xor %dx, %dx | |||
convertdone: | |||
pop %cx | |||
pop %bx | |||
mov %bp, %sp | |||
pop %bp | |||
ret | |||
.type get_number, @function | |||
get_number: | |||
# .enter_char: | |||
# mov $0, %ah | |||
# mov $0, %al | |||
# int $0x16 | |||
# mov $0x0E, %ah | |||
# int $0x10 | |||
# jmp .enter_char | |||
# save state before function | |||
push %bp | |||
mov %sp, %bp | |||
push %bx | |||
push %cx | |||
# Start of function | |||
mWriteString enter_number | |||
mov $0, %ah | |||
mov $0, %al | |||
int $0x16 | |||
mov $0x0E, %ah | |||
int $0x10 | |||
pop %cx | |||
pop %bx | |||
mov %bp, %sp | |||
pop %bp | |||
ret | |||
*/ | |||
#move to 510th byte from the start and append boot signature | |||
. = _start + 510 | |||
.byte 0x55 | |||
.byte 0xaa |
@ -1,337 +0,0 @@ | |||
%macro print_format 1 | |||
lea si, [%1] | |||
call _print_format | |||
%endmacro | |||
%macro print_format 2 | |||
lea si, [%1] | |||
push %2 | |||
call _print_format | |||
add sp, 2 | |||
%endmacro | |||
%macro print_format 3 | |||
lea si, [%1] | |||
push %3 | |||
push %2 | |||
call _print_format | |||
add sp, 4 | |||
%endmacro | |||
%macro print_format 4 | |||
lea si, [%1] | |||
push %4 | |||
push %3 | |||
push %2 | |||
call _print_format | |||
add sp, 6 | |||
%endmacro | |||
%macro print_format 5 | |||
lea si, [%1] | |||
push %5 | |||
push %4 | |||
push %3 | |||
push %2 | |||
call _print_format | |||
add sp, 8 | |||
%endmacro | |||
%macro print_format 6 | |||
lea si, [%1] | |||
push %6 | |||
push %5 | |||
push %4 | |||
push %3 | |||
push %2 | |||
call _print_format | |||
add sp, 10 | |||
%endmacro | |||
%macro print_format 7 | |||
lea si, [%1] | |||
push %7 | |||
push %6 | |||
push %5 | |||
push %4 | |||
push %3 | |||
push %2 | |||
call _print_format | |||
add sp, 12 | |||
%endmacro | |||
BITS 16 | |||
dumpmem_hardcoded_args: | |||
mov si, sp | |||
mov si, [si] | |||
mov cx, 400 | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
dumpmem: | |||
; Dumps memory | |||
; IN 'si': Start address to dump from | |||
; IN 'cx': Number of bytes do dump | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
pusha | |||
xor edx, edx | |||
.loop: | |||
mov ax, word [esi + 2*edx] | |||
inc edx | |||
call dumpax | |||
mov ax, (0xE<<8)|' ' ; print space | |||
int 0x10 | |||
loop .loop | |||
.end: | |||
popa | |||
ret | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
dumpax: | |||
; Prints the contens of ax as a hexadecimal number | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
pusha ; save registers | |||
mov dx, ax | |||
mov ah, 0xE ; Teletype output | |||
mov cx, 4 ; 4 nibbles in a 16 bit word | |||
.print_loop: | |||
rol dx, 4 ; rotate to next nibble | |||
mov al, dl ; we copy to al because we need to mask only the low 4 bits | |||
and al, 0xF ; Do the masking | |||
add al, '0' ; convert to ASCII | |||
; If we are greater than 9 ascii... | |||
cmp al, '9' | |||
jbe .skip_diff_to_ascii_A | |||
add al, 'A'-('9'+1) ; ...add 7 to make digits 10 to 15 be represented as 'A' to 'F' | |||
.skip_diff_to_ascii_A: | |||
int 0x10 ; BIOS call 'output' | |||
loop .print_loop | |||
popa ; restore registers | |||
ret | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
dumpax10: | |||
; Prints the contens of ax as a decimal number | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
pusha | |||
mov bx, 10 ; Divisor | |||
xor cx, cx ; Digit count starts at 0 | |||
.loop_divide: ; finds digits and pushes them to stack | |||
test ax, ax | |||
jz .break_loop_divide | |||
xor dx, dx | |||
div bx ; dx = (dx:ax)%bx, ax = (dx:ax)/bx | |||
push dx | |||
inc cx ; Increase digit count | |||
jmp .loop_divide | |||
.break_loop_divide: | |||
.loop_print: | |||
pop ax | |||
add al, '0' ; Convert to ascii | |||
mov ah, 0xE | |||
int 0x10 | |||
loop .loop_print | |||
popa | |||
ret | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
dumpax_char: | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
mov ah, 0xE | |||
int 0x10 | |||
ret | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
keyprint: | |||
; Enters a loop where the keycode of each pressed key is printed | |||
; [ESC] exits the loop | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
pusha | |||
mov si, .f_info | |||
call print | |||
.keyprint_loop: | |||
mov ax, 0x1000 ; BIOS call to wait for key | |||
int 0x16 | |||
mov bx, ax ; Save KeyCode in bx | |||
print_format .f, ax, ax | |||
cmp bx, 0x011B ; ESC key | |||
je .break_keyprint_loop | |||
jmp .keyprint_loop | |||
.break_keyprint_loop: | |||
popa | |||
ret | |||
.f_info: db 13, 10, "Press keys to see their keycodes.",13,10,"Press [ESC] to exit.", 13, 10, 0 | |||
.f: db "(%c: %x)", 13, 10, 0 | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
dump_stack_registers: | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
push si | |||
print_format .format_string, sp, bp | |||
pop si | |||
ret | |||
.format_string: db "StackRegisters(SP:%x BP:%x)", 0 | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
dump_general_registers: | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
push si | |||
print_format .format_string, ax, cx, dx, bx, si, di | |||
pop si | |||
ret | |||
.format_string: db "GeneralRegisters(ax:%x cx:%x dx:%x bx:%x si:%x di:%x)", 0 | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
dump_segment_registers: | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
push si | |||
print_format .format_string, ss, cs, ds, es, fs, gs | |||
pop si | |||
ret | |||
.format_string: db "SegmentRegisters(Stack:%x Code:%x Data:%x Extra:%x F:%x G:%x)", 0 | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
_print_format: | |||
; IN: variable number of 16-bit numbers on stack | |||
; IN: 'si' points to beginning of format string with the following format: | |||
; %x in string replaced with hexadecimal representation | |||
; %d in string replaced with decimal representation | |||
; %% in string replaced with literal % sign | |||
; | |||
; EXAMPLE call: | |||
; push word 1337 | |||
; push word 0xbeef | |||
; push word 0xdead | |||
; lea si, [.FORMAT] | |||
; call print_format ; output: "(DEAD-BEEF){1337} 100%" | |||
; add sp, 6 | |||
; (...) | |||
; .FORMAT: db "(%x-%x){%d} 100%%",0 | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
push bp | |||
mov bp, sp | |||
pushf | |||
pusha | |||
lea bp, [bp+4] | |||
.outer_loop: | |||
mov ah, 0xE ; Specify 'int 0x10' 'teletype output' function | |||
.print_loop: | |||
lodsb ; al = *si++ | |||
cmp al, '%' | |||
je .break_print | |||
test al, al | |||
jz .break_outer | |||
int 0x10 | |||
jmp .print_loop | |||
.break_print: | |||
lodsb | |||
cmp al, 'x' | |||
je .format_hex | |||
cmp al, 'd' | |||
je .format_dec | |||
cmp al, 'c' | |||
je .format_char | |||
cmp al, '%' | |||
je .print_literal_percent | |||
.format_hex: | |||
lea cx, [dumpax] | |||
jmp .print_ax | |||
.format_dec: | |||
lea cx, [dumpax10] | |||
jmp .print_ax | |||
.format_char: | |||
lea cx, [dumpax_char] | |||
.print_ax: | |||
mov ax, [bp] | |||
lea bp, [bp+2] | |||
call cx | |||
jmp .outer_loop | |||
.print_literal_percent: | |||
mov ax, (0xE<<8)|'%' | |||
int 0x10 | |||
jmp .outer_loop | |||
.break_outer: | |||
popa | |||
popf | |||
pop bp | |||
ret | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
dump_dx_as_two_chars: | |||
; IN dh: first char | |||
; IN dl: second char | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
push ax | |||
mov ah, 0xE | |||
mov al, dh | |||
int 0x10 | |||
mov al, dl | |||
int 0x10 | |||
pop ax | |||
ret | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
dump_status_flags: | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
pushf | |||
push si | |||
push ax | |||
push bx | |||
lahf | |||
mov bl, ah | |||
lea si, [.flags_string] | |||
mov ah, 0xE ; Specify 'int 0x10' 'teletype output' function | |||
.outer_loop: | |||
; [AL = Character, BH = Page Number, BL = Colour (in graphics mode)] | |||
.print_loop: | |||
lodsb ; Load byte at address SI into AL, and increment SI | |||
cmp al, '%' | |||
je .break_print_loop ; If the character is zero (NUL), stop writing the string | |||
test al, al | |||
jz .break_outer_loop | |||
int 0x10 ; Otherwise, print the character via 'int 0x10' | |||
jmp .print_loop ; Repeat for the next character | |||
.break_print_loop: | |||
ror bl, 1 | |||
mov al, bl | |||
and al, 1 | |||
add al, '0' | |||
int 0x10 | |||
jmp .outer_loop | |||
.break_outer_loop: | |||
pop bx | |||
pop ax | |||
pop si | |||
popf | |||
ret | |||
.flags_string: db "Flags(Sign:% Zero:% ?:% Adjust:% ?:% Parity:% ?:% Carry:%)", 0 |
@ -1,72 +0,0 @@ | |||
BITS 16 | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
print: | |||
; Prints string in si | |||
; IN si: zero terminated string to print | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
mov ah, 0xE ; Specify 'int 0x10' 'teletype output' function | |||
; [AL = Character, BH = Page Number, BL = Colour (in graphics mode)] | |||
.printchar: | |||
lodsb ; Load byte at address SI into AL, and increment SI | |||
test al, al | |||
jz .done ; If the character is zero (NUL), stop writing the string | |||
int 0x10 ; Otherwise, print the character via 'int 0x10' | |||
jmp .printchar ; Repeat for the next character | |||
.done: | |||
ret | |||
printCRLF: | |||
mov ah, 0xE | |||
mov al, 13 | |||
int 0x10 | |||
mov al, 10 | |||
int 0x10 | |||
ret | |||
printSpace: | |||
mov ax, 0xE20 | |||
int 0x10 | |||
ret | |||
printALChar: | |||
mov ah, 0xE | |||
mov bl, 0x02 ;color | |||
int 0x10 | |||
ret | |||
; Changing the screen the user i looking at. | |||
; value in 'al' is the screen we want to switch to. | |||
; starting from 0x00 | |||
os_change_screen: | |||
; Here the addresses for the screens stack | |||
; and base pointer has to be set. | |||
mov ah, 0x05 | |||
int 0x10 | |||
ret | |||
os_clear_screen: | |||
pusha | |||
; move cursor to the bootom | |||
xor ax, ax | |||
xor bx, bx | |||
mov ah, 0x02 | |||
mov bh, 0x00 ; page number 0 | |||
mov dh, 0x18 ; row zero | |||
mov dl, 0x00 ; coloumn zero | |||
int 0x10 | |||
xor cx, cx | |||
.loop: | |||
call printCRLF | |||
add cx, 1 | |||
cmp cx, 0x19 ; until blank screen | |||
jne .loop | |||
; Move curser back to the top of the screen | |||
mov ah, 0x02 | |||
mov bh, 0x00 ; page number 0 | |||
mov dh, 0x00 ; row zero | |||
mov dl, 0x00 ; coloumn zero | |||
int 0x10 | |||
popa | |||
ret |
@ -1,39 +0,0 @@ | |||
BITS 16 | |||
; THIS LIBARY IS IN REALLY BAD SHAPE | |||
; Power_off is okay to use | |||
power_check: | |||
;perform an installation check | |||
mov ah,53h ;this is an APM command | |||
mov al,00h ;installation check command | |||
xor bx,bx ;device id (0 = APM BIOS) | |||
int 15h ;call the BIOS function through interrupt 15h | |||
call printCRLF | |||
call dumpax | |||
;jc APM_error ;if the carry flag is set there was an error | |||
;the function was successful | |||
;AX = APM version number | |||
;AH = Major revision number (in BCD format) | |||
;AL = Minor revision number (also BCD format) | |||
;BX = ASCII characters "P" (in BH) and "M" (in BL) | |||
;CX = APM flags (see the official documentation for more details) | |||
ret | |||
power_enable: | |||
;Enable power management for all devices | |||
mov ah,53h ;this is an APM command | |||
mov al,08h ;Change the state of power management... | |||
mov bx,0001h ;...on all devices to... | |||
mov cx,0001h ;...power management on. | |||
int 15h ;call the BIOS function through interrupt 15h | |||
;jc APM_error ;if the carry flag is set there was an error | |||
ret | |||
power_off: | |||
;actual shutdown command | |||
mov ah, 0x53 | |||
mov al, 0x07 | |||
mov bx, 0x1 | |||
mov cx, 0x3 | |||
int 0x15 | |||
ret |
@ -1,57 +0,0 @@ | |||
BITS 16 | |||
; Compares two strings | |||
; IN si: the first (zero terminated) string | |||
; IN di: the second (zero terminated) string | |||
; OUT SF and ZF (same semantics as cmp) | |||
stringcompare: | |||
push bx | |||
push si | |||
push di | |||
.loop: | |||
mov bl, [si] | |||
mov bh, [di] | |||
cmp bl, bh | |||
jne .end | |||
test bl, bl ; bl and bh are the same, so bl = 0 => dl = 0 | |||
jz .end | |||
inc si | |||
inc di | |||
jmp .loop | |||
.end: | |||
pop di | |||
pop si | |||
pop bx | |||
ret | |||
zstring_to_integer: | |||
;IN: si Pointer to string | |||
;OUT: ax result in binary | |||
push bx | |||
push si | |||
push cx | |||
push dx | |||
xor ax, ax | |||
xor bx, bx | |||
xor cx, cx | |||
xor dx, dx | |||
mov bx, 10 | |||
.loop: | |||
mov cl, [si] | |||
cmp cl, 0 | |||
je .end | |||
sub cl,'0' | |||
cmp cl, 9 | |||
ja .end ; next number is not a number, or its a zero, and then we are done | |||
; multiply by 10, and add the new number. | |||
mul bx | |||
add ax, cx | |||
inc si | |||
jmp .loop | |||
.end: | |||
pop dx | |||
pop cx | |||
pop si | |||
pop bx | |||
ret |
@ -1,290 +0,0 @@ | |||
BITS 16 | |||
svim: | |||
pusha ; save state before program | |||
;mov si, .os_clear_screen_str | |||
;call print | |||
xor bx, bx | |||
call os_clear_screen | |||
;xor cx, cx ; Upper and left coordinate | |||
;mov bh, 0x0a ; color for new screen 0 = black a = light green | |||
;mov dh, 0xff ; Select all screen | |||
;mov dl, 0xff ; Select all screen | |||
;mov ah, 0x07 ; scrool down | |||
;mov al, 0x00 ; scrool 0 lines (means blank screen ) | |||
;int 0x10 | |||
mov ah, 0x02 | |||
mov bh, 0x00 ; page number 0 | |||
mov dh, 0x00 ; row zero | |||
mov dl, 0x17 ; coloumn zero | |||
int 0x10 | |||
mov si, .welcome_svim_select_file | |||
call print | |||
call printCRLF | |||
mov si, .seperate_line | |||
call print | |||
call vsfs_list_files_command | |||
; move cursor to the bootom | |||
xor ax, ax | |||
xor bx, bx | |||
mov ah, 0x02 | |||
mov bh, 0x00 ; page number 0 | |||
mov dh, 0x17 ; row zero | |||
mov dl, 0x00 ; coloumn zero | |||
int 0x10 | |||
mov si, .welcome_svim | |||
call print | |||
call printCRLF | |||
mov si, .welcome_svim_enter_fileindex | |||
call print | |||
; Ask the user for the filename | |||
xor bx, bx | |||
xor cx, cx ; are going to be the counter | |||
xor dx, dx | |||
.enter_fileindex_loop: | |||
push cx | |||
.loop_no_push: | |||
mov ax, 0x10 ; BIOS call to wait for key | |||
int 0x16 | |||
cmp ax, 0x1c0d ; enter key | |||
je .fileindex_done | |||
cmp ax, 0x0e08 ; backspace | |||
jne .no_enter_fileindex | |||
cmp cx, 0 | |||
je .loop_no_push | |||
pop cx | |||
sub cx, 1 | |||
mov bx, .buffer_for_svim | |||
add bx, cx | |||
mov BYTE [bx], 0 | |||
; Go back one space | |||
mov ax, 0x0e08 ; ah=0x0e means teletype output. al=0x08 means backspace character. | |||
int 0x10 | |||
; Place a NULL | |||
mov al, 0x0 ; NULL | |||
int 0x10 | |||
; Go back one space again as the above print of NULL pushes the cursor forward again. | |||
mov ax, 0x0e08 | |||
int 0x10 | |||
jmp .enter_fileindex_loop | |||
.no_enter_fileindex: | |||
mov bh, 0x00 | |||
mov bl, 0x02 | |||
mov ah, 0x0E | |||
int 0x10 ; print char | |||
pop cx | |||
mov bx, .buffer_for_svim | |||
add bx, cx | |||
mov [bx], al | |||
add cx, 1 | |||
; fileindex must only be 120 chars | |||
cmp cx, 120 | |||
jae .fileindex_done | |||
jmp .enter_fileindex_loop | |||
.fileindex_done: | |||
pop cx ; Cleanup, and now contain filename size | |||
mov ax, cx | |||
add ax, .buffer_for_svim | |||
mov bx, ax | |||
mov BYTE [bx], 0 | |||
mov si, .buffer_for_svim | |||
call zstring_to_integer ; ax now contain the interger index for the file | |||
mov [.fileindex_for_open_file], ax ; save the file index | |||
call os_clear_screen | |||
; move cursor to the bootom | |||
xor ax, ax | |||
xor bx, bx | |||
mov ah, 0x02 | |||
mov bh, 0x00 ; page number 0 | |||
mov dh, 0x17 ; row zero | |||
mov dl, 0x00 ; coloumn zero | |||
int 0x10 | |||
mov si, .seperate_line | |||
call print | |||
mov si, .welcome_svim | |||
call print | |||
; move cursor to the top | |||
xor ax, ax | |||
xor bx, bx | |||
mov ah, 0x02 | |||
mov bh, 0x00 ; page number 0 | |||
mov dh, 0x00 ; row zero | |||
mov dl, 0x00 ; coloumn zero | |||
int 0x10 | |||
; Load from disk and, enter it, into the buffer | |||
mov si, .welcome_svim_select_file | |||
call print | |||
mov ax, [.fileindex_for_open_file] | |||
call dumpax10 | |||
call printCRLF | |||
mov si, .seperate_line | |||
call print | |||
mov ax, [.fileindex_for_open_file] | |||
mov ch, al ; move the fileindex in the ch | |||
mov bx, ds | |||
mov es, bx | |||
xor bx, bx | |||
mov bx, .buffer_for_svim | |||
xor ax, ax | |||
mov ah, 0x02 ;Read sectors from drive | |||
mov al, 0x04 ;Number of sectors to read (8 * 512 = 4096 bytes) | |||
mov cl, 0x01 ;First sector to read (bits 0-5), upper bits of cylinder (bits 6-7) | |||
mov dh, 0x00 ;Head number | |||
mov dl, [global_disk_identifier] ;Drive number | |||
int 0x13 | |||
mov bx, .buffer_for_svim | |||
add bx, 2046 | |||
mov ax, [bx] | |||
mov [.buffer_counter_svim], ax | |||
; print buffer | |||
mov si, .buffer_for_svim | |||
mov es, si | |||
call print | |||
.svim_loop: | |||
xor bx, bx | |||
xor cx, cx | |||
xor dx, dx | |||
mov ax, 0x1000 ; BIOS call to wait for key | |||
int 0x16 | |||
cmp ax, 0x1c0d ; enter key | |||
jne .no_enter | |||
mov bx, .buffer_for_svim | |||
add bx, [.buffer_counter_svim] | |||
mov BYTE [bx], 13 ; put char in the buffer | |||
mov BYTE [bx + 1], 10 ; put char in the buffer | |||
mov bx, [.buffer_counter_svim] | |||
add bx, 0x02 | |||
mov [.buffer_counter_svim], bx | |||
xor bx, bx | |||
xor cx, cx | |||
xor dx, dx | |||
mov ax, 0x0e0d | |||
int 0x10 | |||
mov ax, 0x0e0a | |||
int 0x10 | |||
jmp .svim_loop | |||
.no_enter: | |||
cmp ax, 0x11b ; ESC key | |||
je .end_svim | |||
;cmp ax, 0x3c00 ; f2 key | |||
;je .f_key_pushed | |||
cmp ax, 0x0e08 ; backspace | |||
je .backspace_pushed | |||
mov bx, ax | |||
mov ax, 0xe20 | |||
mov al, bl | |||
mov bx, .buffer_for_svim | |||
add bx, [.buffer_counter_svim] | |||
mov [bx], al ; put char in the buffer | |||
mov bx, [.buffer_counter_svim] | |||
add bx, 0x01 | |||
mov [.buffer_counter_svim], bx | |||
int 0x10 ; print char | |||
jmp .svim_loop | |||
.end_svim: | |||
; save the written buffer | |||
;AH 03h | |||
;AL Sectors To Write Count | |||
;CH Track | |||
;CL Sector | |||
;DH Head | |||
;DL Drive | |||
;ES:BX Buffer Address Pointer | |||
mov ax, [.buffer_counter_svim] | |||
mov bx, .buffer_for_svim | |||
add bx, 2046 | |||
mov [bx], ax | |||
mov bx, ds | |||
mov es, bx | |||
mov bx, .buffer_for_svim | |||
mov ax, [.fileindex_for_open_file] | |||
mov ch, al ; move the fileindex in the ch | |||
mov ah, 0x03 ;Write sectors to drive | |||
mov al, 0x04 ;Number of sectors to write (8 * 512 = 4096 bytes) | |||
mov cl, 0x01 ;First sector to read (bits 0-5), upper bits of cylinder (bits 6-7) | |||
mov dh, 0x00 ;Head number | |||
mov dl, [global_disk_identifier] ;Drive number | |||
int 0x13 ;Low level disk services | |||
; clean up swim | |||
;xor bx, bx | |||
;xor cx, cx ; Upper and left coordinate | |||
;mov bh, 0x0f ; color for new screen 0 = black f = white | |||
;mov dh, 0xff ; Select all screen | |||
;mov dl, 0xff ; Select all screen | |||
;mov ah, 0x07 ; scrool down | |||
;mov al, 0x00 ; scrool 0 lines (means blank screen ) | |||
;int 0x10 | |||
call os_clear_screen | |||
popa | |||
ret | |||
.backspace_pushed: | |||
mov bx, [.buffer_counter_svim] | |||
cmp bx, 0 | |||
je .svim_loop | |||
;print_format .debug_buffer_counter, bx | |||
mov cx, bx | |||
sub cx, 1 | |||
mov bx, .buffer_for_svim | |||
add bx, cx | |||
mov BYTE [bx], 0 | |||
mov [.buffer_counter_svim], cx | |||
;print_format .debug_buffer_counter, cx | |||
; Go back one space | |||
mov ax, 0x0e08 ; ah=0x0e means teletype output. al=0x08 means backspace character. | |||
int 0x10 | |||
; Place a NULL | |||
mov al, 0x0 ; NULL | |||
int 0x10 | |||
; Go back one space again as the above print of NULL pushes the cursor forward again. | |||
mov ax, 0x0e08 | |||
int 0x10 | |||
jmp .svim_loop | |||
;.f_key_pushed: | |||
;mov al, 0x01 ;arg: index 1 | |||
;call os_change_screen | |||
;jmp .svim_loop | |||
;.load_buffer_svim: | |||
.debug_buffer_counter db 'Buffer count: %d', 13, 10, 0 | |||
.welcome_svim db 'Vim like text editor for SingOS, ESC to exit', 0 | |||
.welcome_svim_select_file db 'svim - Open file: ', 0 | |||
.welcome_svim_enter_fileindex db 'Enter fileindex: ', 0 | |||
.seperate_line db '________________________________________________________________________________', 0 | |||
.fileindex_for_open_file dw 0 | |||
.buffer_for_svim times 2048 db 0 ; db 'this is the buffer', 0, times 32 db 0 | |||
.buffer_counter_svim dw 0 |
@ -1,4 +0,0 @@ | |||
BITS 16 | |||
mem_get_zstack_buffer: | |||
; INPUT size of zeroed buffer ax in bytes |
@ -0,0 +1,134 @@ | |||
[bits 16] | |||
[org 0x0600] | |||
%define STAGE1_BASE 0x7c00 | |||
%define STAGE2_BASE 0x0600 | |||
%define STACK_POINTER_MAX 0x2000 | |||
%macro HALT 0 | |||
%%h: | |||
cli | |||
hlt | |||
jmp %%h | |||
%endmacro | |||
%macro CRLF 0 | |||
push ax | |||
mov ax, 0xe00|13 | |||
int 0x10 | |||
mov al, 10 | |||
int 0x10 | |||
pop ax | |||
%endmacro | |||
segment Stage1 vstart=STAGE1_BASE | |||
Stage1: | |||
; Setup segments | |||
cli | |||
xor ax, ax | |||
xor bx, bx | |||
xor cx, cx | |||
xor dx, dx | |||
xor si, si | |||
xor di, di | |||
times 3 inc ax | |||
times 3 inc bx | |||
times 3 inc cx | |||
times 3 inc dx | |||
times 3 inc si | |||
times 4 nop | |||
times 3 inc di | |||
times 40 nop | |||
call PrintAx | |||
call PrintCRLF | |||
mov ax, bx | |||
call PrintAx | |||
call PrintCRLF | |||
mov ax, cx | |||
call PrintAx | |||
call PrintCRLF | |||
mov ax, dx | |||
call PrintAx | |||
call PrintCRLF | |||
mov ax, si | |||
call PrintAx | |||
call PrintCRLF | |||
mov ax, di | |||
call PrintAx | |||
call PrintCRLF | |||
HALT | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
PrintAx: | |||
PrintAxHex: | |||
; Prints the contens of ax as a hexadecimal number | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
pusha ; save registers | |||
mov dx, ax | |||
mov ah, 0xE ; Teletype output | |||
mov cx, 4 ; 4 nibbles in a 16 bit word | |||
.PrintLoop: | |||
rol dx, 4 ; rotate to next nibble | |||
mov al, dl ; we copy to al because we need to mask only the low 4 bits | |||
and al, 0xF ; Do the masking | |||
add al, '0' ; convert to ASCII | |||
; If we are greater than 9 ascii... | |||
cmp al, '9' | |||
jbe .SkipDiffToAsciiA | |||
add al, 'A'-('9'+1) ; ...add 7 to make digits 10 to 15 be represented as 'A' to 'F' | |||
.SkipDiffToAsciiA: | |||
int 0x10 ; BIOS call 'output' | |||
loop .PrintLoop | |||
popa ; restore registers | |||
ret | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
PrintAxDec: | |||
; Prints the contens of ax as a decimal number | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
pusha | |||
mov bx, 10 ; Divisor | |||
xor cx, cx ; Digit count starts at 0 | |||
.LoopDivide: ; finds digits and pushes them to stack | |||
test ax, ax | |||
jz .BreakLoopDivide | |||
xor dx, dx | |||
div bx ; dx = (dx:ax)%bx, ax = (dx:ax)/bx | |||
push dx | |||
inc cx ; Increase digit count | |||
jmp .LoopDivide | |||
.BreakLoopDivide: | |||
.LoopPrint: | |||
pop ax | |||
add al, '0' ; Convert to ascii | |||
mov ah, 0xE | |||
int 0x10 | |||
loop .LoopPrint | |||
popa | |||
ret | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
PrintCRLF: | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
pusha | |||
mov ah, 0xE | |||
mov al, 13 | |||
int 0x10 | |||
mov al, 10 | |||
int 0x10 | |||
popa | |||
ret | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
times 510-($-$$) db 0 ; Zero-pad to boot signature | |||
db 0x55, 0xAA ; Boot signature |
@ -0,0 +1,8 @@ | |||
{ | |||
"folders": | |||
[ | |||
{ | |||
"path": "." | |||
} | |||
] | |||
} |
@ -1,342 +0,0 @@ | |||
BITS 16 | |||
vsfs_format_disk: | |||
; When SingOS it booted for the first time, | |||
; we have to format the disk to create the global structure | |||
; of the VSFS. | |||
pusha | |||
;AH 03h | |||
;AL Sectors To Write Count | |||
;CH Track | |||
;CL Sector | |||
;DH Head | |||
;DL Drive | |||
; Set the es to point to the data segment, | |||
; this is the global segment, where we calculate all | |||
; our adresses from | |||
; ES:BX Buffer Address Pointer | |||
mov bx, ds | |||
mov es, bx | |||
; Set the bx to point to the pointer of the sector we have to write | |||
; to the disk. | |||
mov bx, .vsfs_format_disk_buffer | |||
mov ah, 0x03 ;Write sectors to drive | |||
mov al, 0x01 ;Number of sectors to write (8 * 512 = 4096 bytes) | |||
mov cl, 0x01 ;First sector to read (bits 0-5), upper bits of cylinder (bits 6-7) | |||
mov ch, 0x08 | |||
mov dh, 0x00 ;Head number | |||
mov dl, [global_disk_identifier] ;Drive number | |||
int 0x13 ;Low level disk services | |||
popa | |||
ret | |||
.vsfs_format_disk_buffer db 'VSFS v0.1', 13, 10, '(VerySimpelFileSystem)', 13, 10, 'Developed to SingOS', 13, 10, 'by Jorn Guldberg', 13, 10, 0 ; 66 chars + 8 bytes | |||
times 431 db 0 | |||
dw 8, 0, 9 ; Start index, number of files, next free index | |||
vsfs_get_fs_info: | |||
pusha | |||
mov bx, ds | |||
mov es, bx | |||
mov bx, vsfs_loading_buffer | |||
mov ah, 0x02 ; Read sectors from drive | |||
mov al, 0x01 ; Number of sectors to read (8 * 512 = 4096 bytes) | |||
mov ch, 0x08 ; cylinder | |||
mov cl, 0x01 ; First sector to read (bits 0-5), upper bits of cylinder (bits 6-7) | |||
mov dh, 0x00 ; Head number | |||
mov dl, [global_disk_identifier] ; Drive number | |||
int 0x13 | |||
mov si, vsfs_loading_buffer | |||
call print | |||
popa | |||
ret | |||
vsfs_read_file_index_in_ax: | |||
; INPUT ax = file index | |||
; INPUT bx = filebuffer | |||
pusha ; save all register state | |||
;call vsfs_convert_index_into_regs | |||
;mov bx, .buffer_for_svim | |||
push bx | |||
mov bx, ds | |||
mov es, bx | |||
pop bx | |||
mov ch, al ; Low 8 bits of cylinder | |||
; the file index into ch, we need to calculatet this, if the number is larger than 16-bits | |||
mov ah, 0x02 ; Read sectors from drive | |||
mov al, 0x01 ; Number of sectors to read (8 * 512 = 4096 bytes) | |||
mov cl, 0x01 ; First sector to read (bits 0-5), upper bits of cylinder (bits 6-7) | |||
mov dh, 0x00 ; Head number | |||
mov dl, [global_disk_identifier] ; Drive number | |||
int 0x13 | |||
popa | |||
ret | |||
vsfs_write_file_to_index_in_ax: | |||
pusha ; save all register state | |||
;AH 03h | |||
;AL Sectors To Write Count | |||
;CH Track | |||
;CL Sector | |||
;DH Head | |||
;DL Drive | |||
;ES:BX Buffer Address Pointer | |||
mov bx, ds | |||
mov es, bx | |||
xor bx, bx | |||
;mov bx, .buffer_for_svim | |||
xor cx, cx | |||
xor ax, ax | |||
mov ah, 0x03 ;Write sectors to drive | |||
mov al, 0x01 ;Number of sectors to write (8 * 512 = 4096 bytes) | |||
mov cl, 0x03 ;First sector to read (bits 0-5), upper bits of cylinder (bits 6-7) | |||
mov ch, 0x02 | |||
mov dh, 0x01 ;Head number | |||
mov dl, [global_disk_identifier] ;Drive number | |||
int 0x13 ;Low level disk services | |||
popa | |||
ret | |||
vsfs_convert_index_into_regs: | |||
; This function takes a file index in ax, do the calculations | |||
; to set the registers to the right place at the disk | |||
; CH Track | |||
; CL Sector | |||
; DH Head | |||
; The rest of the parameters is set in the read and write function. | |||
ret | |||
vsfs_create_file: | |||
; ax pointer to filename | |||
; bx size | |||
; cx fileIndex | |||
pusha ; save all register state | |||
mov si, .vsfs_create_file_type_filename | |||
call print | |||
; Ask the user for the filename | |||
xor bx, bx | |||
xor cx, cx ; are going to be the counter | |||
xor dx, dx | |||
.enter_filename_loop: | |||
push cx | |||
mov ax, 0x10 ; BIOS call to wait for key | |||
int 0x16 | |||
cmp ax, 0x1c0d ; enter key | |||
je .filename_done | |||
cmp ax, 0x0e08 ; backspace | |||
jne .no_enter | |||
pop cx | |||
cmp cx, 0 | |||
je .enter_filename_loop | |||
sub cx, 1 | |||
mov bx, .new_filename_buffer | |||
add bx, cx | |||
mov BYTE [bx], 0 | |||
; Go back one space | |||
mov ax, 0x0e08 ; ah=0x0e means teletype output. al=0x08 means backspace character. | |||
int 0x10 | |||
; Place a NULL | |||
mov al, 0x0 ; NULL | |||
int 0x10 | |||
; Go back one space again as the above print of NULL pushes the cursor forward again. | |||
mov ax, 0x0e08 | |||
int 0x10 | |||
jmp .enter_filename_loop | |||
.no_enter: | |||
mov bh, 0x00 | |||
mov bl, 0x02 | |||
mov ah, 0x0E | |||
int 0x10 ; print char | |||
pop cx | |||
mov bx, .new_filename_buffer | |||
add bx, cx | |||
mov [bx], al | |||
add cx, 1 | |||
; filename must only be 120 chars | |||
cmp cx, 120 | |||
jae .filename_done | |||
jmp .enter_filename_loop | |||
.filename_done: | |||
pop cx ; Cleanup, and now contain filename size | |||
mov bx, .new_filename_buffer | |||
add bx, cx | |||
mov BYTE [bx], 0 | |||
call printCRLF | |||
; We first need to know the index for the file. | |||
; The next avaliable index are we going to get from the | |||
; FSinfo sctor of the disk: | |||
mov bx, ds | |||
mov es, bx | |||
mov bx, vsfs_loading_buffer | |||
mov ch, 0x08 ; Low 8 bits of cylinder | |||
; the file index into ch, we need to calculatet this, if the number is larger than 16-bits | |||
mov ah, 0x02 ; Read sectors from drive | |||
mov al, 0x01 ; Number of sectors to read (8 * 512 = 4096 bytes) | |||
mov cl, 0x01 ; First sector to read (bits 0-5), upper bits of cylinder (bits 6-7) | |||
mov dh, 0x00 ; Head number | |||
mov dl, [global_disk_identifier] ; Drive number | |||
int 0x13 | |||
mov ax, [vsfs_loading_buffer + 510] | |||
mov [.to_write_fileindex], ax | |||
; We have to do modulo 4, to know where in the sector the | |||
; file entry has to be written | |||
add DWORD [vsfs_loading_buffer + 510], 1 | |||
add DWORD [vsfs_loading_buffer + 508], 1 | |||
mov bx, vsfs_loading_buffer | |||
mov ah, 0x03 ;Write sectors to drive | |||
mov al, 0x01 ;Number of sectors to write (8 * 512 = 4096 bytes) | |||
mov cl, 0x01 ;First sector to read (bits 0-5), upper bits of cylinder (bits 6-7) | |||
mov ch, 0x08 | |||
mov dh, 0x00 ;Head number | |||
mov dl, [global_disk_identifier] ;Drive number | |||
int 0x13 ;Low level disk services | |||
; Now we have the index in ax. | |||
;AH 03h | |||
;AL Sectors To Write Count | |||
;CH Track | |||
;CL Sector | |||
;DH Head | |||
;DL Drive | |||
; Set the es to point to the data segment, | |||
; this is the global segment, where we calculate all | |||
; our adresses from | |||
; ES:BX Buffer Address Pointer | |||
mov bx, ds | |||
mov es, bx | |||
mov bx, [.to_write_fileindex] | |||
sub bx, 0x07 ; Det skal den bare | |||
mov cl, bl ; First sector to write (bits 0-5), upper bits of cylinder (bits 6-7) | |||
; Set the bx to point to the pointer of the sector we have to write | |||
; to the disk. | |||
mov bx, .new_filename_buffer | |||
mov ah, 0x03 ;Write sectors to drive | |||
mov al, 0x01 ;Number of sectors to write (8 * 512 = 4096 bytes) | |||
mov ch, 0x08 | |||
mov dh, 0x00 ;Head number | |||
mov dl, [global_disk_identifier] ;Drive number | |||
int 0x13 ;Low level disk services | |||
popa | |||
ret | |||
.vsfs_create_file_type_filename db 'Enter filename: ', 0 | |||
.new_filename_buffer times 122 db 0 | |||
.new_file_size dw 0, 0 | |||
.to_write_fileindex dw 0 | |||
vsfs_list_files_command: | |||
; This function takes the adress of the first sector of the disk | |||
; which the OS has to know | |||
; the adress is given by ax | |||
; Check which registers to save | |||
pusha | |||
; Load the master table into memory | |||
;mov ax, 8 ; file index for master record | |||
;mov bx, vsfs_loading_buffer ; pointer to the input buffer | |||
;call vsfs_read_file_index_in_ax ; call the fucntion which read the master record | |||
; TODO we might want this to be in memory at all times | |||
; loaded already from boot | |||
mov bx, ds | |||
mov es, bx | |||
mov si, .ls_header | |||
call print | |||
mov si, .seperate_line | |||
call print | |||
mov BYTE [.ls_counter], 1 | |||
.load_next_fileinfo: | |||
add BYTE [.ls_counter], 1 | |||
mov bl, [.ls_counter] | |||
mov cl, bl ; First sector to read (bits 0-5), upper bits of cylinder (bits 6-7) | |||
mov bx, vsfs_loading_buffer | |||
;mov ch, al ; Low 8 bits of cylinder | |||
; the file index into ch, we need to calculatet this, if the number is larger than 16-bits | |||
mov ah, 0x02 ; Read sectors from drive | |||
mov al, 0x01 ; Number of sectors to read (8 * 512 = 4096 bytes) | |||
mov ch, 0x08 ; cylinder | |||
mov dh, 0x00 ; Head number | |||
mov dl, [global_disk_identifier] ; Drive number | |||
int 0x13 | |||
mov ax, [vsfs_loading_buffer + 126] | |||
mov bx, ax | |||
mov cx, ' ' | |||
mov dx, 'X' | |||
cmp ax, 0 | |||
je .end_ls | |||
cmp ax, 10 | |||
ja .index_over_10 | |||
mov [.fileentry_line + 3 ], cx | |||
mov [.fileentry_line + 4 ], cx | |||
add bx, 48 ; get ascii value | |||
mov [.fileentry_line + 5 ], bl | |||
jmp .stop_index | |||
.index_over_10: | |||
cmp ax, 10 | |||
ja .index_over_100 | |||
mov [.fileentry_line + 3 ], cx | |||
mov [.fileentry_line + 4 ], dx | |||
mov [.fileentry_line + 5 ], dx | |||
jmp .stop_index | |||
.index_over_100: | |||
mov [.fileentry_line + 3 ], dx | |||
mov [.fileentry_line + 4 ], dx | |||
mov [.fileentry_line + 5 ], dx | |||
.stop_index: | |||
mov si, .fileentry_line ; printing the buffer | |||
call print | |||
mov si, vsfs_loading_buffer ; printing the buffer | |||
call print | |||
call printCRLF | |||
mov si, .seperate_line | |||
call print | |||
jmp .load_next_fileinfo | |||
.end_ls: | |||
popa | |||
ret | |||
.ls_counter db 0 | |||
.ls_header db 'List of files:', 13, 10, 'Index | Filename ', 13, 10, 0 | |||
.seperate_line db '- - - - - - - - - - - - - - - - ', 13, 10, 0 | |||
.fileentry_line db ' 456 | ', 0 | |||
vsfs_loading_buffer times 512 db 0 |
@ -0,0 +1,45 @@ | |||
[bits 16] | |||
%macro HALT 0 | |||
%%h: | |||
cli | |||
hlt | |||
jmp %%h | |||
%endmacro | |||
segment Stage1 vstart=0x7c00 | |||
Stage1: | |||
jmp short .to | |||
times 40-($-$$) db 0 | |||
.to: | |||
xor ax, ax | |||
mov es, ax | |||
mov bx, 0x7c00 | |||
; mov ax, 0x0201 | |||
; mov cx, 0x0003 | |||
; xor dh, dh | |||
; pusha | |||
; int 0x13 | |||
; popa | |||
mov ax, 0x0301 | |||
mov cx, 0x0004 | |||
xor dh, dh | |||
int 0x13 | |||
mov cx, 16 | |||
xchg bx, ax | |||
.loop: | |||
mov ax, 0x0e00 | ('0'>>1) | |||
shl bx, 1 | |||
rcl al, 1 | |||
int 0x10 | |||
loop .loop | |||
HALT | |||
times 510-($-$$) db 0 ; Zero-pad to boot signature | |||
db 0x55, 0xAA ; Boot signature | |||
times 512 db 0 | |||
times 512 db 0xff |