org 0x100 cpu 8086 bits 16 section .code setup: ; Save original video mode mov ah, 0xf int 0x10 mov [original_video_mode], al ; Move to VGA 320x200 256 color mode mov ah, 0 mov al, 0x13 int 0x10 ; Set es to point to VGA framebuffer mov ax, 0xa000 mov es, ax mainloop: ; Check keyboard mov ah, 6 mov dl, 0xff int 0x21 jz .no_key .key: cmp al, 'q' je exit cmp al, 27 je exit .no_key: ; Check time mov ah, 0x2c int 0x21 cmp ch, [hour] jne .changed cmp cl, [minute] jne .changed cmp dh, [second] jne .changed jmp .unchanged .changed: call clear_screen mov [hour], ch mov [minute], cl mov [second], dh mov ax, [second] mul word [six] mov bx, ax mov ax, [width] shr ax, 1 shr ax, 1 call sinx mov bp, [width] shr bp, 1 mov bp, ax mov byte [es:bp], 7 .unchanged: hlt jmp mainloop exit: ; Restore video mode mov ah, 0 mov al, [original_video_mode] int 0x10 ret clear_screen: push bp xor bp, bp .loop: mov word [es:bp], 0 add bp, 2 cmp bp, 320*200 jne .loop pop bp ret ; in: ; ax = scale ; bx = angle ; out: ; ax = scale·cos(angle) cosx: push bx ; cos(x) = sin(x + 90°) add bx, 90 call sinx pop bx ret ; in: ; ax = scale ; bx = angle ; out: ; ax = scale·sin(angle) sinx: push bx push dx .get_in_range: cmp bx, 360 jb .in_range sub bx, 360 jmp .get_in_range .in_range: ; sin(90°) = 1 .angle_90: cmp bx, 90 je .end ; Main branch of function 0 ≤ bx < 90 .q1: cmp bx, 90 ja .q2 ; Load sin(bx) * 2¹⁶ into bx shl bx, 1 mov bx, [sin_table + bx] ; Compute ax·bx and take high 16 bits, which cancel out the ; pre-multiplication of the sin_table mul bx mov ax, dx jmp .end ; sin(bx) = sin(180° - bx) for 90 < bx ≤ 180 .q2: cmp bx, 180 ja .q3_q4 mov dx, 180 sub dx, bx mov bx, dx call sinx jmp .end ; sin(bx) = -sin(bx - 180°) for 180 < bx < 360 .q3_q4: sub bx, 180 call sinx neg ax .end: pop dx pop bx ret section .rodata width dw 320 height dw 200 sin_table: dw 0 ; sin(0°) dw 1143 ; sin(1°) dw 2287 ; sin(2°) dw 3429 ; sin(3°) dw 4571 ; sin(4°) dw 5711 ; sin(5°) dw 6850 ; sin(6°) dw 7986 ; sin(7°) dw 9120 ; sin(8°) dw 10252 ; sin(9°) dw 11380 ; sin(10°) dw 12504 ; sin(11°) dw 13625 ; sin(12°) dw 14742 ; sin(13°) dw 15854 ; sin(14°) dw 16961 ; sin(15°) dw 18064 ; sin(16°) dw 19160 ; sin(17°) dw 20251 ; sin(18°) dw 21336 ; sin(19°) dw 22414 ; sin(20°) dw 23486 ; sin(21°) dw 24550 ; sin(22°) dw 25606 ; sin(23°) dw 26655 ; sin(24°) dw 27696 ; sin(25°) dw 28729 ; sin(26°) dw 29752 ; sin(27°) dw 30767 ; sin(28°) dw 31772 ; sin(29°) dw 32767 ; sin(30°) dw 33753 ; sin(31°) dw 34728 ; sin(32°) dw 35693 ; sin(33°) dw 36647 ; sin(34°) dw 37589 ; sin(35°) dw 38521 ; sin(36°) dw 39440 ; sin(37°) dw 40347 ; sin(38°) dw 41243 ; sin(39°) dw 42125 ; sin(40°) dw 42995 ; sin(41°) dw 43852 ; sin(42°) dw 44695 ; sin(43°) dw 45525 ; sin(44°) dw 46340 ; sin(45°) dw 47142 ; sin(46°) dw 47929 ; sin(47°) dw 48702 ; sin(48°) dw 49460 ; sin(49°) dw 50203 ; sin(50°) dw 50931 ; sin(51°) dw 51643 ; sin(52°) dw 52339 ; sin(53°) dw 53019 ; sin(54°) dw 53683 ; sin(55°) dw 54331 ; sin(56°) dw 54963 ; sin(57°) dw 55577 ; sin(58°) dw 56175 ; sin(59°) dw 56755 ; sin(60°) dw 57319 ; sin(61°) dw 57864 ; sin(62°) dw 58393 ; sin(63°) dw 58903 ; sin(64°) dw 59395 ; sin(65°) dw 59870 ; sin(66°) dw 60326 ; sin(67°) dw 60763 ; sin(68°) dw 61183 ; sin(69°) dw 61583 ; sin(70°) dw 61965 ; sin(71°) dw 62328 ; sin(72°) dw 62672 ; sin(73°) dw 62997 ; sin(74°) dw 63302 ; sin(75°) dw 63589 ; sin(76°) dw 63856 ; sin(77°) dw 64103 ; sin(78°) dw 64331 ; sin(79°) dw 64540 ; sin(80°) dw 64729 ; sin(81°) dw 64898 ; sin(82°) dw 65047 ; sin(83°) dw 65176 ; sin(84°) dw 65286 ; sin(85°) dw 65376 ; sin(86°) dw 65446 ; sin(87°) dw 65496 ; sin(88°) dw 65526 ; sin(89°) six dw 6 section .data hour dw 0 minute dw 0 second dw 0 original_video_mode db 0