osmk 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
osmk-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,242 @@
1
+ Metadata-Version: 2.4
2
+ Name: osmk
3
+ Version: 0.1.0
4
+ Summary: Write x86 operating systems in Python — one instruction at a time
5
+ Author-email: Your Name <you@example.com>
6
+ License: MIT
7
+ Keywords: os,assembly,x86,bootloader,osdev,low-level
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Intended Audience :: Education
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Topic :: System :: Operating System Kernels
13
+ Requires-Python: >=3.9
14
+ Description-Content-Type: text/markdown
15
+ Provides-Extra: dev
16
+ Requires-Dist: pytest>=7.0; extra == "dev"
17
+
18
+ # osmk
19
+
20
+ **Write x86 operating systems in Python — one instruction at a time.**
21
+
22
+ Every function call maps to an x86 assembly instruction. `build()` assembles it into a bootable 512-byte disk image.
23
+
24
+ ## Install
25
+
26
+ ```bash
27
+ pip install osmk
28
+ ```
29
+
30
+ You also need **NASM** (the assembler) and optionally **QEMU** (to run your OS):
31
+
32
+ ```bash
33
+ # Ubuntu/Debian
34
+ sudo apt install nasm qemu-system-x86
35
+
36
+ # macOS
37
+ brew install nasm qemu
38
+ ```
39
+
40
+ ## Quick Start
41
+
42
+ ```python
43
+ import osmk
44
+ from osmk import ax, bx
45
+
46
+ osmk.start("hello.img") # begin a new OS
47
+
48
+ osmk.ax(5) # mov ax, 5
49
+ osmk.bx(5) # mov bx, 5
50
+ osmk.add(ax, bx) # add ax, bx → ax = 0x000A
51
+ osmk.writehex() # print AX as hex → "000A"
52
+
53
+ osmk.build() # assemble → hello.img (512 bytes)
54
+ ```
55
+
56
+ Run it:
57
+ ```bash
58
+ qemu-system-i386 -drive format=raw,file=hello.img
59
+ ```
60
+
61
+ ## API Reference
62
+
63
+ ### Lifecycle
64
+
65
+ | Function | Description |
66
+ |----------|-------------|
67
+ | `start(filename, bits=16, org=0x7C00)` | Begin a new OS program |
68
+ | `build()` | Assemble and create the bootable image |
69
+ | `dump_asm()` | Return the generated NASM source (for debugging) |
70
+ | `run(memory=128)` | Build and launch in QEMU |
71
+
72
+ ### Register Setters
73
+
74
+ Every register is callable. `osmk.ax(5)` → `mov ax, 5`.
75
+
76
+ ```python
77
+ osmk.ax(5) # mov ax, 5
78
+ osmk.bx(ax) # mov bx, ax
79
+ osmk.al(0x41) # mov al, 0x41
80
+ osmk.eax(0x1000) # mov eax, 0x1000
81
+ ```
82
+
83
+ Available: `ax bx cx dx si di sp bp` · `al ah bl bh cl ch dl dh` · `eax ebx ecx edx esi edi esp ebp`
84
+
85
+ ### Instructions
86
+
87
+ ```python
88
+ # Arithmetic
89
+ osmk.add(ax, bx) osmk.sub(ax, 1)
90
+ osmk.mul(bx) osmk.div(cx)
91
+ osmk.inc(ax) osmk.dec(cx)
92
+ osmk.neg(ax)
93
+
94
+ # Bitwise
95
+ osmk.and_(ax, 0xFF) osmk.or_(ax, bx)
96
+ osmk.xor(ax, ax) osmk.not_(ax)
97
+ osmk.shl(ax, 4) osmk.shr(ax, 1)
98
+
99
+ # Compare & Jump
100
+ osmk.cmp(ax, 0)
101
+ osmk.je("done") osmk.jne("loop")
102
+ osmk.jl("less") osmk.jg("greater")
103
+ osmk.jz("zero") osmk.jnz("nonzero")
104
+ osmk.jmp("start") osmk.jc("carry")
105
+
106
+ # Stack
107
+ osmk.push(ax) osmk.pop(bx)
108
+
109
+ # Subroutines
110
+ osmk.call("myfunc") osmk.ret()
111
+
112
+ # Interrupts
113
+ osmk.interrupt(0x10) # int 0x10
114
+ osmk.cli() osmk.sti()
115
+ osmk.hlt()
116
+
117
+ # Labels
118
+ osmk.label("loop")
119
+ ```
120
+
121
+ ### Output Helpers
122
+
123
+ ```python
124
+ osmk.writehex() # print AX as 4-digit hex (e.g. "000A")
125
+ osmk.writechar("A") # print character 'A'
126
+ osmk.writechar() # print whatever's in AL
127
+ osmk.prints("Hello!") # print a string
128
+ osmk.newline() # print CR+LF
129
+ osmk.readchar() # wait for keypress → AL
130
+ osmk.halt() # halt CPU (cli + hlt loop)
131
+ ```
132
+
133
+ ### Custom / Escape Hatch
134
+
135
+ When osmk doesn't cover what you need:
136
+
137
+ ```python
138
+ # Inject raw NASM assembly
139
+ osmk.asm("mov ah, 0x0E")
140
+ osmk.asm("""
141
+ mov ah, 0x00
142
+ mov al, 0x03
143
+ int 0x10
144
+ """)
145
+
146
+ # Inject raw bytes
147
+ osmk.raw(b"\x90\x90\x90") # 3x NOP
148
+
149
+ # Define data
150
+ osmk.data("my_var", "dw 0x1234")
151
+
152
+ # Define a subroutine
153
+ with osmk.function("beep") as fn:
154
+ fn.asm("mov ah, 0x0E")
155
+ fn.asm("mov al, 0x07") # BEL character
156
+ fn.asm("int 0x10")
157
+
158
+ osmk.call("beep")
159
+
160
+ # Add comments
161
+ osmk.comment("this sets up video mode")
162
+ ```
163
+
164
+ ### Explicit MOV
165
+
166
+ ```python
167
+ osmk.mov(ax, 0x0E) # same as osmk.ax(0x0E)
168
+ osmk.mov(bx, ax) # same as osmk.bx(ax)
169
+ ```
170
+
171
+ ## Examples
172
+
173
+ ### Hello World
174
+ ```python
175
+ import osmk
176
+
177
+ osmk.start("hello.img")
178
+ osmk.prints("Hello, World!")
179
+ osmk.newline()
180
+ osmk.prints("My first OS!")
181
+ osmk.halt()
182
+ osmk.build()
183
+ ```
184
+
185
+ ### Keyboard Echo
186
+ ```python
187
+ import osmk
188
+ from osmk import cx
189
+
190
+ osmk.start("echo.img")
191
+ osmk.prints("Type anything:")
192
+ osmk.newline()
193
+
194
+ osmk.label("loop")
195
+ osmk.readchar() # key → AL
196
+ osmk.writechar() # echo it
197
+ osmk.jmp("loop")
198
+
199
+ osmk.build()
200
+ ```
201
+
202
+ ### Counter
203
+ ```python
204
+ import osmk
205
+ from osmk import ax, cx
206
+
207
+ osmk.start("counter.img")
208
+
209
+ osmk.ax(0)
210
+ osmk.cx(16)
211
+
212
+ osmk.label("count")
213
+ osmk.writehex()
214
+ osmk.prints(" ")
215
+ osmk.inc(ax)
216
+ osmk.dec(cx)
217
+ osmk.jnz("count")
218
+
219
+ osmk.halt()
220
+ osmk.build()
221
+ ```
222
+
223
+ ## How It Works
224
+
225
+ 1. Each `osmk.*` call appends an x86 assembly instruction to an internal list
226
+ 2. `build()` wraps them in a bootloader template (16-bit real mode, MBR)
227
+ 3. NASM assembles it into a flat binary
228
+ 4. The binary is exactly 512 bytes with the `0xAA55` boot signature
229
+
230
+ The generated code runs in **16-bit real mode** using BIOS interrupts for I/O. Use `dump_asm()` to see exactly what assembly your Python generates.
231
+
232
+ ## Resources
233
+
234
+ - [OSDev Wiki](https://wiki.osdev.org/) — OS development reference
235
+ - [NASM Documentation](https://nasm.us/doc/) — assembler docs
236
+ - [x86 Instruction Reference](https://www.felixcloutier.com/x86/) — complete instruction set
237
+ - [Writing a Simple OS](https://www.cs.bham.ac.uk/~exr/lectures/opsys/10_11/lectures/os-dev.pdf) — Nick Blundell's guide
238
+ - [BIOS Interrupt List](https://en.wikipedia.org/wiki/BIOS_interrupt_call) — int 0x10, 0x13, 0x16, etc.
239
+
240
+ ## License
241
+
242
+ MIT
osmk-0.1.0/README.md ADDED
@@ -0,0 +1,225 @@
1
+ # osmk
2
+
3
+ **Write x86 operating systems in Python — one instruction at a time.**
4
+
5
+ Every function call maps to an x86 assembly instruction. `build()` assembles it into a bootable 512-byte disk image.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ pip install osmk
11
+ ```
12
+
13
+ You also need **NASM** (the assembler) and optionally **QEMU** (to run your OS):
14
+
15
+ ```bash
16
+ # Ubuntu/Debian
17
+ sudo apt install nasm qemu-system-x86
18
+
19
+ # macOS
20
+ brew install nasm qemu
21
+ ```
22
+
23
+ ## Quick Start
24
+
25
+ ```python
26
+ import osmk
27
+ from osmk import ax, bx
28
+
29
+ osmk.start("hello.img") # begin a new OS
30
+
31
+ osmk.ax(5) # mov ax, 5
32
+ osmk.bx(5) # mov bx, 5
33
+ osmk.add(ax, bx) # add ax, bx → ax = 0x000A
34
+ osmk.writehex() # print AX as hex → "000A"
35
+
36
+ osmk.build() # assemble → hello.img (512 bytes)
37
+ ```
38
+
39
+ Run it:
40
+ ```bash
41
+ qemu-system-i386 -drive format=raw,file=hello.img
42
+ ```
43
+
44
+ ## API Reference
45
+
46
+ ### Lifecycle
47
+
48
+ | Function | Description |
49
+ |----------|-------------|
50
+ | `start(filename, bits=16, org=0x7C00)` | Begin a new OS program |
51
+ | `build()` | Assemble and create the bootable image |
52
+ | `dump_asm()` | Return the generated NASM source (for debugging) |
53
+ | `run(memory=128)` | Build and launch in QEMU |
54
+
55
+ ### Register Setters
56
+
57
+ Every register is callable. `osmk.ax(5)` → `mov ax, 5`.
58
+
59
+ ```python
60
+ osmk.ax(5) # mov ax, 5
61
+ osmk.bx(ax) # mov bx, ax
62
+ osmk.al(0x41) # mov al, 0x41
63
+ osmk.eax(0x1000) # mov eax, 0x1000
64
+ ```
65
+
66
+ Available: `ax bx cx dx si di sp bp` · `al ah bl bh cl ch dl dh` · `eax ebx ecx edx esi edi esp ebp`
67
+
68
+ ### Instructions
69
+
70
+ ```python
71
+ # Arithmetic
72
+ osmk.add(ax, bx) osmk.sub(ax, 1)
73
+ osmk.mul(bx) osmk.div(cx)
74
+ osmk.inc(ax) osmk.dec(cx)
75
+ osmk.neg(ax)
76
+
77
+ # Bitwise
78
+ osmk.and_(ax, 0xFF) osmk.or_(ax, bx)
79
+ osmk.xor(ax, ax) osmk.not_(ax)
80
+ osmk.shl(ax, 4) osmk.shr(ax, 1)
81
+
82
+ # Compare & Jump
83
+ osmk.cmp(ax, 0)
84
+ osmk.je("done") osmk.jne("loop")
85
+ osmk.jl("less") osmk.jg("greater")
86
+ osmk.jz("zero") osmk.jnz("nonzero")
87
+ osmk.jmp("start") osmk.jc("carry")
88
+
89
+ # Stack
90
+ osmk.push(ax) osmk.pop(bx)
91
+
92
+ # Subroutines
93
+ osmk.call("myfunc") osmk.ret()
94
+
95
+ # Interrupts
96
+ osmk.interrupt(0x10) # int 0x10
97
+ osmk.cli() osmk.sti()
98
+ osmk.hlt()
99
+
100
+ # Labels
101
+ osmk.label("loop")
102
+ ```
103
+
104
+ ### Output Helpers
105
+
106
+ ```python
107
+ osmk.writehex() # print AX as 4-digit hex (e.g. "000A")
108
+ osmk.writechar("A") # print character 'A'
109
+ osmk.writechar() # print whatever's in AL
110
+ osmk.prints("Hello!") # print a string
111
+ osmk.newline() # print CR+LF
112
+ osmk.readchar() # wait for keypress → AL
113
+ osmk.halt() # halt CPU (cli + hlt loop)
114
+ ```
115
+
116
+ ### Custom / Escape Hatch
117
+
118
+ When osmk doesn't cover what you need:
119
+
120
+ ```python
121
+ # Inject raw NASM assembly
122
+ osmk.asm("mov ah, 0x0E")
123
+ osmk.asm("""
124
+ mov ah, 0x00
125
+ mov al, 0x03
126
+ int 0x10
127
+ """)
128
+
129
+ # Inject raw bytes
130
+ osmk.raw(b"\x90\x90\x90") # 3x NOP
131
+
132
+ # Define data
133
+ osmk.data("my_var", "dw 0x1234")
134
+
135
+ # Define a subroutine
136
+ with osmk.function("beep") as fn:
137
+ fn.asm("mov ah, 0x0E")
138
+ fn.asm("mov al, 0x07") # BEL character
139
+ fn.asm("int 0x10")
140
+
141
+ osmk.call("beep")
142
+
143
+ # Add comments
144
+ osmk.comment("this sets up video mode")
145
+ ```
146
+
147
+ ### Explicit MOV
148
+
149
+ ```python
150
+ osmk.mov(ax, 0x0E) # same as osmk.ax(0x0E)
151
+ osmk.mov(bx, ax) # same as osmk.bx(ax)
152
+ ```
153
+
154
+ ## Examples
155
+
156
+ ### Hello World
157
+ ```python
158
+ import osmk
159
+
160
+ osmk.start("hello.img")
161
+ osmk.prints("Hello, World!")
162
+ osmk.newline()
163
+ osmk.prints("My first OS!")
164
+ osmk.halt()
165
+ osmk.build()
166
+ ```
167
+
168
+ ### Keyboard Echo
169
+ ```python
170
+ import osmk
171
+ from osmk import cx
172
+
173
+ osmk.start("echo.img")
174
+ osmk.prints("Type anything:")
175
+ osmk.newline()
176
+
177
+ osmk.label("loop")
178
+ osmk.readchar() # key → AL
179
+ osmk.writechar() # echo it
180
+ osmk.jmp("loop")
181
+
182
+ osmk.build()
183
+ ```
184
+
185
+ ### Counter
186
+ ```python
187
+ import osmk
188
+ from osmk import ax, cx
189
+
190
+ osmk.start("counter.img")
191
+
192
+ osmk.ax(0)
193
+ osmk.cx(16)
194
+
195
+ osmk.label("count")
196
+ osmk.writehex()
197
+ osmk.prints(" ")
198
+ osmk.inc(ax)
199
+ osmk.dec(cx)
200
+ osmk.jnz("count")
201
+
202
+ osmk.halt()
203
+ osmk.build()
204
+ ```
205
+
206
+ ## How It Works
207
+
208
+ 1. Each `osmk.*` call appends an x86 assembly instruction to an internal list
209
+ 2. `build()` wraps them in a bootloader template (16-bit real mode, MBR)
210
+ 3. NASM assembles it into a flat binary
211
+ 4. The binary is exactly 512 bytes with the `0xAA55` boot signature
212
+
213
+ The generated code runs in **16-bit real mode** using BIOS interrupts for I/O. Use `dump_asm()` to see exactly what assembly your Python generates.
214
+
215
+ ## Resources
216
+
217
+ - [OSDev Wiki](https://wiki.osdev.org/) — OS development reference
218
+ - [NASM Documentation](https://nasm.us/doc/) — assembler docs
219
+ - [x86 Instruction Reference](https://www.felixcloutier.com/x86/) — complete instruction set
220
+ - [Writing a Simple OS](https://www.cs.bham.ac.uk/~exr/lectures/opsys/10_11/lectures/os-dev.pdf) — Nick Blundell's guide
221
+ - [BIOS Interrupt List](https://en.wikipedia.org/wiki/BIOS_interrupt_call) — int 0x10, 0x13, 0x16, etc.
222
+
223
+ ## License
224
+
225
+ MIT