flat assembler
Message board for the users of flat assembler.
![]() |
Author |
|
neville 14 Jan 2011, 03:19
MiniMON - a mini machine code "monitor" for your PC
- like a simple microprocessor development board ROM - all squeezed into a bootable single 512-byte bootsector! - You can view all conventional RAM and ROM contents 256 bytes at a time - You can change all RAM contents with a hex editor - So you can enter your program machine code in hex (almost) anywhere you like - and then run it using the e(X)ecute key. Code starts executing from the nearest lowest paragraph boundary (XXXX0H) so best to always enter code starting from the left-most screen column i.e. when you press the X key code starts executing from the left-most byte on that row. - code CD 05 for normal program termination, or in emergencies press the PrtSc key (INT 05H) - No room for any on-screen instructions, but the (messy) source code says it all! - Hex numeric keys A - F and X key are not case-sensitive - Navigation of 64K offset addresses using cursor keys and PgDn/PgUp keys - Navigation of segment address using End key - Memory addresses displayed in 20-bit linear format 0SXXXX (not S000:XXXX) Of course once MiniMON has booted it knows nothing about disks, including the device it just booted from. In effect it's about the smallest possible memory operating system, but at the same time it is sufficient to hand-code and test anything you like. Limited only by the imagination! Scroll down to page 7D00 and move the cursor around - watch the changing MEMADDR and CURLOC (CursorLocation) variables stored at word[7DF1] and word[7DF3] in the bottom row. Now every monitor program should have some support for breakpoints but unfortunately there wasn't room in the bootsector ![]() So here's a 20-byte breakpoint handler for the single-byte opcode CCH (INT 3) which can be entered almost anywhere in RAM: B8 03 00 CD 10 90 B8 42 0E CD 10 B4 00 CD 16 EA 00 7C 00 00 OK, as a breakpoint handler it could be improved on - displaying register contents would be nice - but hey, what do you expect in 20 bytes? Let's say you put the breakpoint routine at address 07E00 (the page following the bootsector). Now enter the Interrupt vector address straight into the Interrupt Vector Table: Scroll up (down?) to address 000000 then cursor along to 0000C - 0000F (address for INT 3) and enter 00 7E 00 00 Done! Now you can code breakpoints anywhere you like, with a 90 (NOP) byte that you change to a CC (INT 3) byte when you want a breakpoint. Now to test the breakpoint routine: Write a test program into RAM, lets say at address 012340: B8 DB 0E CD 10 CD 16 CC EB FE This program will hack the screen display by printing a big white block character at the cursor, and then waiting for a keystroke before hitting the breakpoint. After you press any key, the breakpoint routine should clear the screen and print a B in the top left corner and wait for another key. It then returns to the monitor, not your program code. Which is just as well, because after the breakpoint is the dreaded dead loop JMP $, code EB FE So change the breakpoint CC to 90 (NOP) and execute it again. Yep, gets kinda cold - a big freeze. But don't panic! You still don't need that boot device because the PrtSc key is your saviour and will take you back to the monitor, no questions asked ![]() Notice there's also provision for a breakpoint in the breakpoint routine, 6th byte. Right after setting the video mode which clears the screen. Find out what happens when the breakpoint routine calls itself... You might need the PrtSc key again! Enjoy! BTW: - Even this simple little program exhibits some of the features of a memory OS, like variables retaining values in memory if desired. - I've written MiniMON into the bootsector of a pendrive (using USBIT - thanks for the tip Mike Gonta), and until I finish hand-coding my USB host controller driver in MiniMON I'm unplugging the pendrive as soon as it boots. Saves wear and tear on the pendrive for the next 25 years until I finish the hcd ![]() - The code is based on MEMED, the Memory Editor I wrote for my MiniMOS os a while ago, which in turn is a vastly cut-down version of the 32-bit flat real FAMOS Memory Editor, FAME.
_________________ FAMOS - the first memory operating system |
|||||||||||
![]() |
|
neville 14 Jan 2011, 03:27
Here's the bootsector image too, all 512 bytes of it
![]()
_________________ FAMOS - the first memory operating system |
|||||||||||
![]() |
|
Coty 15 Jan 2011, 13:42
Cool! It took me a while but I was eventually able to make a jump loop
![]() ... Crashing QEmu with it was easier ![]() Anyway nice ![]() |
|||
![]() |
|
neville 19 Jan 2011, 02:26
Thanks for your thoughts.
My coding style is that, unless there is good reason otherwise, I generally write for readability and future maintainability rather than optimisation, and I've certainly never worried about "source footprints". In fact, the bigger the source the better because it's probably got more comments and is generally more readable ![]() As mentioned this code was originally written for FAMOS using 32-bit registers, and the binary was about 3kb. Chopping out all the screen text reduced it to under 1kb, and then it was just a matter of getting it under 512 bytes which turned out to be quite easy. As you can see, here I am always deriving the required bits in AL, which is easy to read and understand. There is no "magic" ![]() ![]() My use of the SI register does look a bit strange, but I did that in the MiniMOS code to avoid a couple of memory accesses (with segment overrides) which was actually just an easy way of saving quite a few bytes of code. Yes, it could certainly be further optimised. If I'm optimising it's usually for speed rather than code size but of course every byte saved here means more functions could potentially be squeezed into the boot sector.... _________________ FAMOS - the first memory operating system |
|||
![]() |
|
cod3b453 20 Jan 2011, 23:27
Thank you for sharing this neville! This is a very slick way to see what's where at boot time so I know I'm not trashing stuff with my boot loader
![]() |
|||
![]() |
|
neville 23 Jan 2011, 21:35
You are welcome cod3b453
![]() I've just used MiniMON to see what my BIOS thinks my 2Gb pendrive is when it boots. Interestingly, it reports the parameters as 1023 cyls, 16 heads and 32 sectors per track. I would never have guessed 32 SPT !! So the size is only 1023*16*32*512 = 268,173,312 bytes, about 1/8 of its actual size. BTW this was using INT13h/AH=08 which returned CX=FFE0h, DX=0F02h I should be able to access the full 2GB from MiniMON using EDD services though. _________________ FAMOS - the first memory operating system |
|||
![]() |
|
Madis731 24 Jan 2011, 07:24
I tried to code this one from scratch and I had fun. Actually I discovered something new about 16-bit mode. Even if it doesn't support more than 16 bits it still can use 32-wide registers in a funny way. For example when ecx=-1 and I increase cx, the upper half of ecx will not wrap around and point to a different address in memory when addressed with [ecx].
Here are all the 389 bytes of it ![]() PS. Additional feature: character representation of binary data right next to the dump. EDIT (just to be clear about the implementation/functionality): -Code starts executing from the selected byte (not the paragraph like in the original) -PrtSc key (INT 05H) is not implemented
|
|||||||||||
![]() |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2023, Tomasz Grysztar. Also on GitHub, YouTube, Twitter.
Website powered by rwasa.