Author | SHA1 | Message | Date |
---|---|---|---|
|
35edf789e5 | minize | 5 years ago |
|
dafa6183ef | . | 5 years ago |
|
1a3e8f7649 | godnat | 5 years ago |
|
41d4b4a7fb | PROTECTED MODE BABY | 5 years ago |
|
15894ab4c6 | Lets32Bit | 5 years ago |
@ -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 | 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 | #!/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 |