Keyboard input, hex printer
This commit is contained in:
@@ -24,7 +24,11 @@ Hello world programs that run without an operating system.
|
||||
1. [reboot](reboot.S)
|
||||
1. [Not testable in userland](not-testable-in-userland.md)
|
||||
1. [Segment registers real mode](segment_registers_real_mode.S)
|
||||
1 [SS (TODO)](ss.S)
|
||||
1. [SS (TODO)](ss.S)
|
||||
1. [Interrupt](interrupt.S)
|
||||
1. [Interrupt zero divide](interrupt_zero_divide.S)
|
||||
1. in
|
||||
1. [in keyboard](in_keyboard.S)
|
||||
1. APM
|
||||
1. [APM shutdown](apm_shutdown.S)
|
||||
1. [APM shutdown 2](apm_shutdown2.S)
|
||||
|
||||
5
TODO.md
5
TODO.md
@@ -7,7 +7,7 @@
|
||||
|
||||
- instructions
|
||||
|
||||
- wbinvd
|
||||
- cache: wbinvd
|
||||
- outb inb
|
||||
- lgdtl, paging http://stackoverflow.com/questions/21128311/the-physical-address-of-global-descriptor-table http://stackoverflow.com/questions/7415515/problem-accessing-control-registers-cr0-cr2-cr3
|
||||
- lidtl, interrupts, IDTR
|
||||
@@ -25,6 +25,7 @@
|
||||
- http://stackoverflow.com/questions/14480579/when-does-segment-registers-change
|
||||
- http://stackoverflow.com/questions/15335003/x86-protected-mode-segment-registers-purpose
|
||||
- http://stackoverflow.com/questions/17210620/assembler-calculating-a-memory-address-with-register-base?lq=1
|
||||
http://stackoverflow.com/questions/18736663/what-does-the-colon-mean-in-x86-assembly-gas-syntax-as-in-dsbx
|
||||
- http://stackoverflow.com/questions/20717890/how-to-interpret-gs0x14?lq=1
|
||||
- http://stackoverflow.com/questions/22446104/do-the-x86-segment-registers-have-special-meaning-usage-on-modern-cpus-and-oses?lq=1
|
||||
- http://stackoverflow.com/questions/26058665/fs-register-in-assembly-code?lq=1
|
||||
@@ -57,8 +58,6 @@
|
||||
|
||||
- ACPI
|
||||
|
||||
- reboot computer. Would put QEMU into an infinite reboot loop! Awesome. http://stackoverflow.com/questions/32682152/how-to-reboot-in-x86-assembly-from-16-bit-real-mode
|
||||
|
||||
- multithreading: http://stackoverflow.com/questions/7308391/how-is-concurrency-done-in-intel-x86-assembly || http://stackoverflow.com/questions/980999/what-does-multicore-assembly-language-look-like || http://stackoverflow.com/questions/714905/threads-in-x86-assembler-using-the-gnu-assember-as || https://github.com/cirosantilli/oszur11-operating-system-examples/tree/1af6451852887fac3d7206d4d09714c181c81d1e/Chapter_07_Threads
|
||||
|
||||
- play with hardware
|
||||
|
||||
@@ -13,6 +13,6 @@ Carriage returns are needed just like in old days.
|
||||
BEGIN
|
||||
PRINT($msg)
|
||||
hlt
|
||||
END
|
||||
msg:
|
||||
.asciz "hello\n\rworld"
|
||||
END
|
||||
|
||||
@@ -13,6 +13,6 @@ Carriage returns are needed just like in old days.
|
||||
BEGIN
|
||||
PRINT($msg)
|
||||
hlt
|
||||
END
|
||||
msg:
|
||||
.asciz "hello\nworld"
|
||||
END
|
||||
|
||||
@@ -36,15 +36,8 @@ which gets filled with the background color in bh.
|
||||
#include "common.h"
|
||||
BEGIN
|
||||
|
||||
/* Print staircase. */
|
||||
CLEAR
|
||||
PUTC($0x61)
|
||||
PUTC($0x0A)
|
||||
PUTC($0x62)
|
||||
PUTC($0x0A)
|
||||
PUTC($0x63)
|
||||
PUTC($0x0A)
|
||||
PUTC($0x64)
|
||||
PRINT($stair)
|
||||
|
||||
/* Function ID. */
|
||||
mov $0x06, %ah
|
||||
@@ -70,3 +63,5 @@ int $0x10
|
||||
|
||||
hlt
|
||||
END
|
||||
stair:
|
||||
.asciz "a\nb\nc\nd"
|
||||
|
||||
40
common.h
40
common.h
@@ -50,6 +50,40 @@ Usage: character 'A' (ASCII 61):
|
||||
mov c, %al;\
|
||||
int $0x10
|
||||
|
||||
/*
|
||||
Convert a byte to hex ASCII value.
|
||||
c: r/m8 byte to be converted
|
||||
Output: two ASCII characters, is stored in `al:bl`
|
||||
http://stackoverflow.com/questions/3853730/printing-hexadecimal-digits-with-assembly
|
||||
*/
|
||||
#define HEX(c) GAS_HEX c
|
||||
.macro GAS_HEX c
|
||||
mov \c, %al
|
||||
mov \c, %bl
|
||||
shr $4, %al
|
||||
GAS_HEX_NIBBLE al
|
||||
and $0x0F, %bl
|
||||
GAS_HEX_NIBBLE bl
|
||||
.endm
|
||||
|
||||
/*
|
||||
Convert the low nibble of a r8 reg to ASCII of 8-bit in-place.
|
||||
reg: r8 to be converted
|
||||
Output: stored in reg itself. Letters are uppercase.
|
||||
*/
|
||||
.macro GAS_HEX_NIBBLE reg
|
||||
LOCAL letter, end
|
||||
cmp $10, %\reg
|
||||
jae letter
|
||||
/* 0x30 == '0' */
|
||||
add $0x30, %\reg
|
||||
jmp end
|
||||
letter:
|
||||
/* 0x37 == 'A' - 10 */
|
||||
add $0x37, %\reg
|
||||
end:
|
||||
.endm
|
||||
|
||||
/*
|
||||
Print a null terminated string.
|
||||
|
||||
@@ -65,14 +99,14 @@ We use this `cpp` macro to allow writing `PRINT(S)` with parenthesis.
|
||||
#define PRINT(s) GAS_PRINT s
|
||||
/* We need a Gas macro for the LOCAL labels. */
|
||||
.macro GAS_PRINT s
|
||||
LOCAL halt, loop
|
||||
LOCAL loop, end
|
||||
mov s, %si
|
||||
mov $0x0e, %ah
|
||||
loop:
|
||||
lodsb
|
||||
or %al, %al
|
||||
jz halt
|
||||
jz end
|
||||
int $0x10
|
||||
jmp loop
|
||||
halt:
|
||||
end:
|
||||
.endm
|
||||
|
||||
33
in_keyboard.S
Normal file
33
in_keyboard.S
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
Whenever you press a key up or down,
|
||||
the keyboard hex scancode is printed to the screen.
|
||||
|
||||
Only changes in state are shown.
|
||||
|
||||
Scancode tables: TODO: official specs?
|
||||
|
||||
- http://flint.cs.yale.edu/cs422/doc/art-of-asm/pdf/APNDXC.PDF
|
||||
- https://en.wikipedia.org/wiki/Scancode
|
||||
|
||||
TODO Where does the 0x60 come from? http://wiki.osdev.org/I/O_Ports has a small list.
|
||||
|
||||
TODO Possible to do this with the interrupt table instead of `in`?
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
BEGIN
|
||||
CLEAR
|
||||
/* TODO why CLI makes no difference? We are not using interrupts? */
|
||||
/*cli*/
|
||||
loop:
|
||||
in $0x60, %al
|
||||
cmp %al, %cl
|
||||
jz loop
|
||||
mov %al, %cl
|
||||
HEX(<%al>)
|
||||
PUTC(%al)
|
||||
PUTC(%bl)
|
||||
PUTC($0x0A)
|
||||
PUTC($0x0D)
|
||||
jmp loop
|
||||
END
|
||||
15
interrupt.S
15
interrupt.S
@@ -1,12 +1,11 @@
|
||||
/*
|
||||
Minimal interrupt example.
|
||||
|
||||
Upon division by zero, the interrupt handler is run,
|
||||
and it prints the character 'A' to screen.
|
||||
Should print the characters 'ab' to screen.
|
||||
|
||||
TODO: is STI not needed because this interrupt is not maskable?
|
||||
|
||||
TODO: use IDTR. Is initial value guaranteed?
|
||||
TODO: use IDTR as a base. Is the initial value 0 guaranteed?
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
@@ -14,11 +13,13 @@ BEGIN
|
||||
CLEAR
|
||||
movw $handler, 0x00
|
||||
movw $0x00, 0x02
|
||||
mov $0x00, %ax
|
||||
div %ax
|
||||
jmp fail
|
||||
int $0
|
||||
PUTC($0x62)
|
||||
jmp end
|
||||
handler:
|
||||
PUTC($0x61)
|
||||
fail:
|
||||
/* Returns to the int instruction. */
|
||||
iret
|
||||
end:
|
||||
hlt
|
||||
END
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
/*
|
||||
TODO get working
|
||||
TODO get working. Vs `in_keyboard`?
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
BEGIN
|
||||
CLEAR
|
||||
/*
|
||||
I've read that the keyboard handler is the number 1 (second one),
|
||||
and each entry is 4 byte wide.
|
||||
*/
|
||||
movw $handler, 0x04
|
||||
movw $0x00, 0x06
|
||||
sti
|
||||
@@ -12,5 +16,6 @@ loop:
|
||||
jmp loop
|
||||
handler:
|
||||
PUTC($0x61)
|
||||
iret
|
||||
jmp loop
|
||||
END
|
||||
|
||||
17
interrupt_zero_divide.S
Normal file
17
interrupt_zero_divide.S
Normal file
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
Same as doing an `int $0`.
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
BEGIN
|
||||
CLEAR
|
||||
movw $handler, 0x00
|
||||
movw $0x00, 0x02
|
||||
mov $0x00, %ax
|
||||
div %ax
|
||||
jmp fail
|
||||
handler:
|
||||
PUTC($0x61)
|
||||
fail:
|
||||
hlt
|
||||
END
|
||||
2
mbr.md
2
mbr.md
@@ -12,6 +12,8 @@ TODO where is it specified, if at all?
|
||||
|
||||
- BIOS loads the program into memory at the address `0x7C00`.
|
||||
|
||||
Note that this is not the first address that the RIP is set to run: I think all jobs up to now are done by the CPU: the first address seems to be `FFFF:0000` instead: <http://stackoverflow.com/a/32686533/895245>
|
||||
|
||||
We must tell that magic number to the linker somehow, either with a linker script, `-tText=-Ttext 0x7C00` or NASM `org 0x7c00`.
|
||||
|
||||
This will only matter when you access a memory address, because of relocation.
|
||||
|
||||
Reference in New Issue
Block a user