ghaerr / elks

Embeddable Linux Kernel Subset - Linux for 8086
Other
1k stars 108 forks source link

Games development on ELKS #871

Open toncho11 opened 3 years ago

toncho11 commented 3 years ago

Let's take this example of Snake compiled by Turbo C:

https://github.com/ashmew2/snake-game/blob/master/Final.cpp

@ghaerr Maybe graphics.h can be mapped to Nano-X? But on 8086 computers Naxo-X looks slow for games. For example

toncho11 commented 1 year ago

https://drive.google.com/file/d/1DzPUphhR1RLh7H31fNWnmNi8W6db5wjZ/view?usp=sharing

It slows down on the mouse cursor. This is on 8 MHz 8086.

ghaerr commented 1 year ago

This is on 8 MHz 8086.

Thanks. This shows how slow a full screen clear (blue to black) is, pretty slow. And when the mouse cursor is obstructing the window, the routine uses a much slower clipped version as we can see.

My take is that we could possibly use nano-X for some games that don't require too high speed graphics. There is an ntetris game in the Microwindows repo at microwindows/src/demos/nanox/ntetris.c. I wonder if we should bring that over to ELKS?

Here's ntetris on SDL:

nxtetris
toncho11 commented 1 year ago

Yes, that will be a good demo. Something really playable will be good. But maybe some speed optimizations will be needed. Maybe disabling: mouse support entirely, clipping (if there is no overlapping in the game), messaging. Also checking for an event can be done less frequently (every second time in a loop).

ghaerr commented 1 year ago

Hello @toncho11,

I ported nxtetris from Microwindows to ELKS, I'll post a PR shortly to build it. I'm having some troubles with the timing, its going a bit too fast in QEMU, which has some known time issues with ELKS. Give it a try on one of your older machines and see how it works. You can use the keyboard j/k/s/d and space keys to operate it, and ESC to quit. nxtetris.zip

Here it is running on QEMU:

https://user-images.githubusercontent.com/11985637/219929002-db454c58-9b94-4cb4-b720-bc325deba2f2.mov

tyama501 commented 1 year ago

Hello @ghaerr ,

Wow! that's great. Does it need mouse? If no, it may work for PC-98 too. (If disk space available...)

toncho11 commented 1 year ago

Morning here. It works on my Amstrad 8086 8 MHz. IMG_20230219_090550 Yes, it moves a bit fast. Slowing it down will also make the animation more fluent. There should be an option for the speed.

Fantastic job @ghaerr !!! When polished we should put it on the front page!!!

toncho11 commented 1 year ago

Hello @ghaerr ,

Wow! that's great. Does it need mouse? If no, it may work for PC-98 too. (If disk space available...)

No mouse. "n" for new game.

ghaerr commented 1 year ago

Hello @toncho11,

Thanks for the testing and the screenshot. Looks like it's definitely running too fast for you 😂.

I'm having some trouble getting the timing working, not sure if its the game, Nano-X or ELKS. Good idea about speed options, I'll add + and - to change speeds.

Thank you!

ghaerr commented 1 year ago

If no, it may work for PC-98 too. (If disk space available...)

Yes, it should work fine with the PC-98 screen driver compiled in, which is automatic for the PC-98 build. I'm adding the game to the :other category, but there's definitely not enough space to fit along with everything else on a 1232K or 1440K floppy.

toncho11 commented 1 year ago

Myabe there can be another 1440 image dedicated to games and nxdemos in the future.

tyama501 commented 1 year ago

Myabe there can be another 1440 image dedicated to games and nxdemos in the future.

Agree. At least I would like to distribute the FD image with elksmoria and nx applications in my repository.

tyama501 commented 1 year ago

Hello @ghaerr ,

I could play nxtetris with PC-98 driver.

Here is the picture and video. It is PC-9801RX21 with intel 80286, 12MHz. The default game speed is good for me to play.

ELKS_nxtetris_IMG_20230223_023410_small

https://user-images.githubusercontent.com/61556504/220713898-7c5d4d84-76cb-4e1e-98fa-425ddd7cff80.mp4

Thank you!

ghaerr commented 1 year ago

Hello @tyama501,

That's great news to hear that nxtetris works using your nano-X screen driver with no modifications! It seems the new timing code based on clock ticks is also working correctly. Also nano-X seems to work well for drawing on slower PCs, providing that the amount of screen changes is not too great at once.

I'll look into how we might create an additional disk of programs/games for IBM PC and PC-98. It is a bit complicated since disk format would have to be chosen as well.

It would be nice to test nxtetris or other games with a mouse... I think this should work now, provided that a Microsoft compatible mouse is present on the serial port.

Thank you!

toncho11 commented 1 year ago

Next can be Pong: https://www.youtube.com/watch?v=GrjFGI9TTkE&t=69s&ab_channel=Squakenet

ATroubleshooter commented 1 year ago

Hello @ghaerr ! Tried nxtetris and it runs just perfect, thank you.

toncho11 commented 1 year ago

I just tested nxtetris on a 486 and a 8088 IBM 4.77 Mhz and both were OK. Here is the 1.44 MB image: fd1440-fat-nxtetris.zip

ghaerr commented 1 year ago

Glad to hear that @toncho11, thank you for the testing. I haven't forgot about the other small changes either, as I have been deep into blink16 programming and haven't come up for air.

toncho11 commented 1 year ago

Games on Elks probably deserves a wiki page.

ghaerr commented 1 year ago

Games on Elks probably deserves a wiki page.

You're welcome to open one, I closed this as there hasn't been much action on actually porting DOS games over, and wanted to start with fresh issues as we move into v0.8.0.

toncho11 commented 1 year ago

There is an open source version of bgi https://sourceforge.net/projects/openbgi/ that can be ported to ELKS.

ghaerr commented 1 year ago

@toncho11, I've reopened this to continue discussions on game programing, thanks!

toncho11 commented 1 year ago

Started a page on the wiki: https://github.com/ghaerr/elks/wiki/Games

tyama501 commented 1 year ago

@toncho11 Thank you!

Vutshi commented 5 months ago

Hi guys, I just found out about the Doom8088 port. I'm curious about the feasibility of porting it to ELKS. It's interesting to note that it uses gcc-ia16.

Best

ghaerr commented 5 months ago

Hi @Vutshi,

What, now you want Doom8088 on your Book8088 running ELKS?! :)

I had been following this project, and taking a look just now it appears that @FrenkelS has indeed completed a Doom port compiled with ia16-elf-gcc for DOS. Pretty cool! The port is using mregparmcall (pass function parameters in registers) and medium model (code <= 128K) both of which are supported on ELKS. Its using Newlib for the C library, which should be no problem replacing with ELKS libc. Not sure whether the code size is < 128k, which is required by ELKS.

The port has an ASM driver for BIOS mode 13, which is 256-color 320x200 VGA, and the driver looks to be drawing directly to the VGA hardware, which is good. We'd probably have to minimally change some code for possibly BIOS mode switching, keyboard I/O (mouse not supported), and memory allocations, depending on whether the data segment size is < 64K.

It's using some compiler options I'm not familiar with (-fgcse-sm -fgcse-las -fipa-pta -fwhole-program -funroll-loops -freorder-blocks-algorithm=simple) and is also compiled for 286. I'm not sure whether it'll run on an 8088 or not.

Overall, I would say it sounds promising a port could be somewhat easily be completed, providing the code segment is 128k or less. I suppose I should pull it down and try a quick compile to look a little further at it.

Thank you!

FrenkelS commented 5 months ago

It might be easier to port doomtd3 first. It's a stripped down version of Doom8088 that only runs the benchmark demo, no interactivity, no sound. It runs in the 640x200 monochrome mode, though. It has been ported to the Macintosh Plus and the Amiga 500.

I'm also not sure what all those compiler options do. It just seems to output faster code. mregparmcall is only important when assembly is used, but that's not necessary, look at the macro C_ONLY.

toncho11 commented 5 months ago

Even if it works (in the beginning) only on 386 it will still be amazing considering the compatibility ia16-elf-gcc.

ghaerr commented 5 months ago

I took a dive into Doom8088, produced a new Makefile and got all source except for some DOS-related routines to compile. With the heavy loop-rolling optimizations on, the code segment is > 128K, which is too large to link. Compiling those routines without the heavy optimization allows everything to fit into with about 26k to spare. I don't know how this might affect the speed of the game, especially on older systems. For the time being, its compiling for 286 architecture.

It's using some compiler options I'm not familiar with (-fgcse-sm -fgcse-las -fipa-pta -fwhole-program -funroll-loops -freorder-blocks-algorithm=simple)

These compiler options perform multi-pass loop optimization and loop unrolling. There were also additional link time optimization options given (e.g.-flto, etc) which had to be removed as it appears link time optimization isn't supported by the ELKS linker ld.gold. Given the above, this means an initial port would be unoptimized, and possibly pretty slow.

I underestimated the work required to do a full ELKS port - Doom handles its own keyboard, reprograms the clock hardware and interrupt, and directly updates and chains IRQ vectors, all of which need to be rewritten for ELKS. In addition, it appears it uses _dos_allocmem to grab all remaining main memory for its use. This also will need some rethinking for ELKS, but is doable using fmemalloc, but the amount of memory available could vary greatly depending on ELKS main memory checkerboarding. It is unknown as to whether Doom8088 will run without a large contiguous far data segment. The full set of far string/memory routines like _fmemset, _fmemcpy, _fstrcpy, etc also need to be ported, but that's a fairly straightforward job using @tkchia's Lib86 project. Not sure whether it would be worth trying to port those portions of Lib86 to ELKS or rewrite them for Doom8088 in Intel ASM format, as there are other Intel-format ASM files used in Doom8088.

I don't really have the time for continuing a full port of Doom, but for anyone that's interested, I'm happy to share a patch file that gets the code compiling and linking w/undefined functions as described above.

toncho11 commented 5 months ago

As always @ghaerr you are doing hercules job! Than you!!! I think it got a few of us quite excited! Did you see the comment above that it will be easier to port doomtd3 first? It's a stripped down version of Doom8088.

ghaerr commented 5 months ago

I haven't looked at doomtd3, but figure that most of the work remains the same, which is that the DOS related stuff needs rewriting, lib86 routines need porting, and probably needs the same memory allocation routines, even if the game WAD is smaller. The sound stuff can be easily skipped in a first port of Doom8088. The monochrome-only output is less interesting, and I've ported Doom to a number of platforms before, most recently Microwindows. Our ELKS version of Microwindows is too constrained for a Doom port though, and @FrenkelS has it running on bare VGA hardware which is faster anyways.

Vutshi commented 5 months ago

Hi @ghaerr

What, now you want Doom8088 on your Book8088 running ELKS?! :)

I must admit, I was tempted. But after running the doomtd3 benchmark on MartyPC, a cycle-exact 8088 emulator, and witnessing the remarkable performance Doomtd3_martyPC_short I’m not so certain anymore :)

I also tried WolfensteinCGA on Book8088. It overheated and froze within 5 minutes on an overclocked Intel 8088. For such experiments, NEC V20 is a must-have.

On the other hand, Doom is a must-have for justifying the existence of an operating system. I’m thrilled about the possibility of an ELKS port. However, the work required for porting seems a bit above my pay grade. If no one more skilled steps up for this noble task, I might find time to experiment with porting in the near future.

Best.

toncho11 commented 5 months ago

@ghaerr maybe you can create a fork of Doom3d that has the new Makefile that allows the compilation and outline all of the above tasks that are needed in order for the port to be completed.

ghaerr commented 5 months ago

Hello @Vutshi and @toncho11,

Here's a full patch file and the new Makefile for building Doom8088 on ELKS (from commit 4839c17a09c667bbcb9e2db5634ab8b85fb3be5e) on Sun Apr 28 2024:

doom8088-elks.zip

running the doomtd3 benchmark on MartyPC, a cycle-exact 8088 emulator, and witnessing the remarkable performance

Wow, that really is slow. We can expect Doom8088 to be even slower.

I’m not so certain anymore :)

I would say Doom on ELKS is doomed unless running on a fast 386.

I might find time to experiment with porting in the near future.

That'd be great. Some time needs to be spent figuring out what parts of the hardware IRQ, timer, keyboard and similar other stuff is really needed for and then we can work together to figure how to make that work on ELKS. In general, ELKS applications don't really want to mess with any IRQ vectoring into the application as that has the potential to interfere greatly with the kernel during time slicing. The undefined far string routines shown during link can probably be quickly written in C for a first pass, rather than worrying about an ASM implementation.

FrenkelS commented 5 months ago

What, now you want Doom8088 on your Book8088 running ELKS?! :)

I must admit, I was tempted. But after running the doomtd3 benchmark on MartyPC, a cycle-exact 8088 emulator, and witnessing the remarkable performance Doomtd3_martyPC_short I’m not so certain anymore :)

Thanks for trying it out. I'm working on a 40x25 version. Right now it runs about 50% faster than the 60x128 + status bar version.

ghaerr commented 5 months ago

Some time needs to be spent figuring out what parts of the hardware IRQ, timer, keyboard and similar other stuff is really needed

More information for those wanting to work on porting Doom to ELKS: I looked at my old port of Doom to Microwindows and quickly realized it's a Linux port - that is, Doom runs on Linux while connecting to Nano-X for the graphics. This means that all of the Linux timer stuff has already been figured out, and we don't need to go through the painstaking details of un-DOS-ifying the Doom8088 port. In particular, the i_system.c file can probably by used as a replacement in whole for Doom8088/i_system.c as a starting point, while looking at each routine for exceptions.

There are other Nano-X routines in v_video.c in my port that deal with keyboard input, these will have to be replaced by select() on stdin wherever that kind of stuff is handled in Doom8088. The point is that most of the routines for interfacing with Linux will also apply to ELKS, in general, except direct VGA output will be used from Doom8088, not Nano-X.

The Doom8088 files a_pcfx.c (sound) and a_taskmn.c (timer interrupt for keyboard polling and sound) can probably be removed from the build. Doom8088 has no mouse support so we don't need to worry about that.

@FrenkelS, I notice there are a number of .LMP files in the WAD/ directory. Are these used in Doom8088? Also, where is the Doom8088 WAD file downloaded from?

FrenkelS commented 5 months ago

Creating the Doom8088 wad file is a bit of a mess, that I want to automate someday. Just grab the WAD from the latest Doom8088 release.

The process starts by using GbaWadUtil on the shareware wad file. This utility

After that I use Slade to add those 4 .LMP files by hand, and the PC speaker sound effects. And I compress the level data some more. And I compress the wall textures and sprites.

Those 4 .LMP files are the graphics for the status bar, title screen, the map that's shown between levels and a screen when the game is finished. Doom8088 is based on GBADoom. In that port these full screen graphics are the same files as in vanilla Doom. But these files are more than 64 kB, so they're to big for Doom8088. So I use smaller files instead.

Vutshi commented 4 months ago

Hi @ghaerr, I am trying to port something simple to ELKS as a warm-up exercise. The Mandelbrot seems to be simple enough. However, I’m unsure how to use gcc-ia16 with the assembly file due to a syntax difference from the wiki example. Best

ghaerr commented 4 months ago

Hello @Vutshi,

I haven't actually used "Intel" style ASM (i.e. using nasm rather than gcc's as) with gcc-elf-ia16, but have used it with other C code compiled with gcc. As the wiki example recommends, you just need to assemble the Intel-style assembly using a more recent version of nasm and specifying ELF output: nasm -f elf file.s; this should produce a compatible file.o that can then be linked with other gcc-elf-i16 .o files normally. You will have to remove lines from mandelbrot like "cpu 8086", ".org 100", etc.

I do also notice that mandelbrot resets the hardware timer and resets the timer interrupt vector, as well as resets DS to CS creating its own special segments... none of that kind of stuff will run under ELKS. We can discuss that in more detail should you really want to try to port mandelbrot. But basically one is not allowed to change DS or SS in ELKS programs nor play with interrupts or much hardware directly, other than perhaps the EGA in special cases.

In order to look at the compiled or disassembled output of .o files, I use ia16-elf-objdump -D -r -Mi8086 file.o.

Actually as I read the wiki article, it looks correct as far I as I am reading. Perhaps you can post the error message(s) you're getting using nasm -f elf here and we can try to better determine what problems you are having.

Unless you're stuck on porting that mandelbrot, perhaps using a program written in GNU ASM souce might be better (or a C program with a much smaller ASM component)... the C compiler outputs AT&T syntax, and it is quite hard switching back and forth between the two since the operands for every instruction are reversed.

Vutshi commented 4 months ago

Hi @ghaerr,

The Mandelbrot code is assembled using yasm, which I have realised is quite similar to nasm, albeit with some differences. I get successful DOS outcome running:

yasm mandel.asm -o mandel.com

At the same time nasm gives me error:

nasm mandel.asm -o mandel.com              
mandel.asm:52: error: shift operator may only be applied to scalar values

Now if I comment out cpu 8086 and org 0x100 and try to generate elf yasm complains about the same line:

yasm -f elf mandel.asm -o mandel.o
mandel.asm:52: error: expression too complex

For some reason cpu 8086 is important for yasm to resolve the address calculation in the line 52. However, in this case it gives different errors:

yasm -f elf mandel.asm -o mandel.o 
mandel.asm:336: error: short jump out of range
mandel.asm:338: error: short jump out of range
mandel.asm:351: error: short jump out of range
mandel.asm:353: error: short jump out of range
mandel.asm:366: error: short jump out of range
mandel.asm:368: error: short jump out of range
mandel.asm:381: error: short jump out of range
mandel.asm:383: error: short jump out of range
mandel.asm:396: error: short jump out of range
mandel.asm:398: error: short jump out of range
mandel.asm:466: error: short jump out of range
mandel.asm:468: error: short jump out of range
mandel.asm:470: error: short jump out of range
mandel.asm:495: error: short jump out of range
mandel.asm:562: error: short jump out of range
mandel.asm:564: error: short jump out of range
mandel.asm:589: error: short jump out of range
mandel.asm:660: error: short jump out of range
mandel.asm:665: error: short jump out of range
mandel.asm:766: error: short jump out of range

I do also notice that mandelbrot resets the hardware timer and resets the timer interrupt vector, as well as resets DS to CS creating its own special segments... none of that kind of stuff will run under ELKS.

Luckily Mandelbrot only resets the timer and interrupt vector if the XTSERVER option is enabled, whose purpose is unclear. The program runs fine without it. So the only problem seems to be

one is not allowed to change DS or SS in ELKS

Can I just push pop them or ELKS uses them while the program is being executed?

Thank you.

ghaerr commented 4 months ago

Can I just push pop them or ELKS uses them while the program is being executed?

Looking at the source, it seems DS and SS are only set in lines 50-51 and 63-67 (and 73-74). It seems that this is only for the purpose of initializing DS (to CS) and setting up a stack and stack segment. All this can and must be deleted for ELKS, as the program is started with CS, DS, SS and SP set to proper values. Lines 73-74 appear to set DS for the purpose of initializing some variables, that may need a bit more study. In ELKS, DS will be set to the application data segment and doesn't need changing, although BSS (uninitialized) variables from C would need zeroing.

mandel.asm:52: error: expression too complex

I'm going to leave that one for you to figure out in full detail. It appears that codeEndInit is a segment value of the end of an area to be used past the end of the code segment for data, and likely accessed with DS=CS (see lines 50-51). For the ELKS refactoring, the data variables would be placed in an ASM .data or section .data area and db, dw or the like used for initialization.

For some reason cpu 8086 is important for yasm to resolve the address calculation

Could be that codeEndInit is a special variable in 8086 ASM mode, or just that the default other ASM modes assume a flat address space... ?

mandel.asm:336: error: short jump out of range

This usually means that the signed byte offset in the conditional (short) jump instructions are less than -128 or greater than 127. Perhaps the iterate macro isn't generating the correct code when cpu 8086 isn't specified.

I suppose you'll have to decide whether to use YASM or NASM (or GAS) to assemble this. During the process, you can use the above ia16-elf-objdump to disassemble any produced .o to ensure that the .text and .data sections contain what you want for ELKS to execute properly and that the original Mandelbrot has been translated properly. If YASM will output ELF .o files, you're probably better off just using YASM rather than converting to NASM or GAS, although the latter conversion will teach you a lot about gnu AS and ia16-elf-gcc output!

Vutshi commented 4 months ago

Alright, before I plunged into the horrors of 16-bit assemblers, I took a detour and requested chatGPT to draft a Mandelbrot C code for Intel 8086. To my surprise, it functioned flawlessly on the first try :) Here’s the outcome:

https://github.com/ghaerr/elks/assets/4971779/2a71fbec-14f6-46ec-8102-327bafd42aeb

ghaerr commented 4 months ago

I took a detour and requested chatGPT to draft a Mandelbrot C code for Intel 8086.

Wow, I wonder if that is actually written for 8086 or instead just C code from ChatGPT's training by swallowing up and regurgitating some programmers code on GitHub (I have heard that MSFT allowed all the source on GitHub to be used freely to train ChatGPT w/o regards to licensing... ?)

I would guess that code is just plain C code and not written for 8086 or IBM PC. It seems the ASM Mandelbrot code does draw directly to the console at B800 and uses colors, but I haven't learned yet whether it uses different ASCII or IBM PC characters for "ASCII ART" output. Perhaps ask ChatGPT for that, or an GNU ASM version of Mandelbrot?

Vutshi commented 4 months ago

Here is the chatGPT code. It is horrible in several aspects, in particular it uses double precision :0 text_mandel.txt

The ASM Mandelbrot is lightning fast even on real 8086. It is written by the guy behind the 8088 MPH demo.

ghaerr commented 4 months ago

The ASM Mandelbrot is lightning fast even on real 8086.

Nice! In that case, you're not excused from porting a fast graphical mandelbrot to ELKS :) It could be fun to later modify it to draw graphically to EGA hardware in graphics mode.

It is written by the guy behind the 8088 MPH demo.

You mean Andrew Jenner, the reenigne guy, or someone else? Andrew is pretty amazing, he's the author of a very fast and small 8086 simulator which I used in a 8086 simulator and disassembler before I added the same to the Blink16 project. HIs emulator is extremely basic, fast and well written, one of the smallest I've seen. I effectively took his emulator and created a disassembler from it, which was small enough to work with ELKS at runtime (see elkscmd/debug/disasm.c if interested).

Here is the chatGPT code. It is horrible in several aspects, in particular it uses double precision

If you're looking for a pretty cool ASCII Art Mandelbrot generator, check this out. This was originally written for playing with the serial port on a RiscV machine, but I've got it ready to port to ELKS, and was planning on it, just for fun. I'm not sure yet how fast it is. Here is my modified source as a single .c file:

mand.c.zip

Vutshi commented 4 months ago

It works!!! This simulation is supposed to faithfully represent the Intel 8088 speed:

https://github.com/ghaerr/elks/assets/4971779/c2f73e82-4f07-4299-953e-f6d54a4673d4

Of course now ELKS is stuck because the program still tries to exit to DOS ;) Here is the modified code and the assembled program if someone wants to try it on a real hardware: ELKS_Mandelbrot.zip

The code can be assembled using NASM and converted to an ELKS executable as described in the wiki. The problem of DS SS registers is not yet resolved and the proper exit to ELKS is missing.

ghaerr commented 4 months ago

It works!!!

Nice. I didn't realize it ran in a CGA graphics mode, cool.

Now time to do some ELKS porting...

Of course now ELKS is stuck because the program still tries to exit to DOS

The single mov ax,0x4c00; int 0x21 is the system call to DOS: INT 21h is the "system call" interrupt used, with AH=4Ch to select the system call desired. System calls in ELKS uses int 0x80 instead, with the parameters pushed on the stack in reverse order, and the system call number for exit is 1 in AX. Thus, xor ax,ax; push ax; mov ax,1; int 0x80 should exit properly.

Notice that just above the DOS exit is INT 16h with AH=0. This is the BIOS wait for keypress routine, to display the image until a keypress then exit. BIOS calls aren't allowed in ELKS applications, so you'll want to convert that to the equivalent of read(0, buf, 1). To find the system call number for read, look at elks/arch/i86/kernel/syscall.dat: it is 3. So you'll want to push a literal 1, a buffer address, a 0, then load AX with 3 and execute INT 81h. That will wait for a return to be pressed on file descriptor 0, which is the standard input (console). The buffer can be a 1 byte address in the .data section.

The problem of DS SS registers is not yet resolved

DS and SS will be set to the data section ("section .data") of the program automatically by the ELKS loader, so that code should be able to be carefully removed and have everything work. The SP (stack pointer) will also be set automatically, so the stack location at the end of the source file can also be removed, along with any code setting SS and SP.

Have fun!

Vutshi commented 4 months ago

Hi @ghaerr

I am a bit confused about system calls in ELKS. You recommend to put arguments on stack:

System calls in ELKS uses int 0x80 instead, with the parameters pushed on the stack in reverse order, and the system call number for exit is 1 in AX. Thus, xor ax,ax; push ax; mov ax,1; int 0x80 should exit properly.

The wiki examples put arguments in registers

    mov     dx,len              ;3rd arg: message length
    mov     cx,msg              ;2nd arg: pointer to message to write
    mov     bx,1                ;1st arg: file handle (stdout)
    mov     ax,4                ;system call number (sys_write)
    int     0x80                ;call kernel

                                ;exit now
    mov     bx,0                ;1st syscall arg: exit code
    mov     ax,1                ;system call number (sys_exit)
    int     0x80                ;call kernel

Which method should I use?

Thank you

ghaerr commented 4 months ago

Hello @Vutshi,

I am a bit confused about system calls in ELKS. You recommend to put arguments on stack The wiki put arguments in registers

Argh, I am sorry - you are right. I was thinking about a different system. ELKS system call arguments are passed in registers in the following order: BX, CX, DX, DI, SI. The system call number is in AX.

The parameter calling convention for system calls as well as cdecl and regparm for C is documented here.

The wiki put arguments in registers

The wiki is correct: the parameters for read(0, buf, 1) would be BX=0, CX=buf, DX=1, and AX=3 for read.

Which method should I use?

My apologies for the confusion.

ghaerr commented 4 months ago

If you're looking for a pretty cool ASCII Art Mandelbrot generator

After adding fminf and fmaxf to the math library in #1899, I was able to compile mand.c for ELKS. Here is the ASCII art output:

https://github.com/ghaerr/elks/assets/11985637/24e0b1ff-b87d-44bd-b5a9-543c07808123

Source file: mand.c.zip

Vutshi commented 4 months ago

Hi @ghaerr,

This looks cool! Yet, my poor 8088 struggles with this Mandelbrot set. It is on the level of the first slow sl train.

Meanwhile, I played with the asm Mandelbrot and proper ELKS exit procedure. The most remarkable result so far is that this program has managed to crash martpc emulator.

I noticed it employs an unusual memory layout:

Mandelbrot_memory

It uses two big tables which do not fit into one 64KB segment. The iters table sits at DS:0 (plus some other stuff), and squareTable of size 0x8000 is at ES:0. How can this be accommodated by ELKS ELF?

P.S. Also I tried blink16 for debugging, however it seems to be more strict than the ELKS itself. It stops running the program at a stage of setting up DS, ES, SS registers. Did I misconfigure it somehow?

Best