Open ecm-pushbx opened 3 years ago
Forgot the link: https://hg.pushbx.org/ecm/amitsrs/rev/123031d14d43 This is the commit I made to work around the far string issue.
Hello @ecm-pushbx,
Yes — unfortunately the newlib-ia16
runtime's printf
implementation does not currently grok far pointers. And it seems to be quite non-trivial to add these to the library. (<stdio.h>
support is one of the messier parts of Newlib...)
Your workaround is probably as good as it gets, for the time being. 😐
Thank you!
Hello @tkchia,
support is one of the messier parts of Newlib...
Wow, looking around in newlib-ia16/newlib/libc/stdio/ shows a lot of code and complexity for a 16-bit library, although it does look like it tries to be ANSI X3J11 compliant. There are also "nano" and "full-blown" versions of the low-level vfprintf and vfscanf functions, on top of which most all the other stdio format-interpretation functions rest.
And it seems to be quite non-trivial to add these to the library.
Looking particularly at nano-vfprintf.c, it would seem that, IF the library is built using the "nano" vfprintf, AND the "string-only" version of the library isn't being built, then changing the definition of __sfputs_r
definition as well as the pfunc
signature to use a char __far *buf
as the third parameter could solve most of the problem without too much ugliness. This would allow a far pointer to be passed to the lower level output function (pfunc
), which is statically called in vfprintf_r
. Of course, the other areas where a pfunc
is passed, such as __printf_common
would also need the far pointer signature change.
If the IA-16 library is possibly compiled with a variety of compilation options, the far pointer buffer signature change could manifest into quite a few files, but I'm not sure the library is built separately with many different options?
That change then leaves the problem of the format string to use, and %F is already used for floating point. If perhaps %S were used, instead of a separate prefix option, then a small change in nano-vprintf_i.c for the 's'/'S' case, along with a far _fmemchr
should allow either a DS:ptr or user-passed far pointer to the passed pfunc
routine for output.
I haven't (yet) tried changing to a far signature and compiling to see how many files/functions this could ripple to, so I might be off base here as to the complexity required for this, and/or whether it's even worth the effort.
Thank you!
Hello @tkchia,
Noticing the 'help wanted' on this issue, I took a stab at pulling down newlib-ia16
and tried configuring it but realize it's going to be complicated to understand how to compile and test this with my preferred environment, macOS and ELKS. I thought to as a few questions:
newlib-ia16
be easily configured to use my existing ELKS gcc-ia16
toolchain to compile it? I'm developing on macOS../build.sh
from build-ia16
or another method?
[EDIT: I tried ./fetch.sh
followed by ./build.sh binutils
, and the build immediately failed on incompatible script -e -c
... macOS doesn't support either option. So it would seem this discussion should likely be handled by opening another issue, should that make sense.]gcc-ia16
be linked with this newlib-ia16
? I realize that ELKS has it's own libc, and am very familiar with how some of ELKS libc headers pull in ELKS kernel header files. But for simplicity at this point, having only a matching set of system calls would seem to allow execution and testing of basic stdio programs on ELKS without having to worry about a full-blown port of newlib-ia16
to replace ELKS libc.-I<newlib_hdr_dir>
and -L<newlib_libc_dir>
for compilation and linking. Would just the -melks-libc
option be removed, and/or what other special switches might be necessary?I was never a full fan of ELKS having its own libc. While I'm certainly not proposing newlib-ia16
as a replacement project, the idea of having users of this repository be able to compile and run for an ELKS target might increase the usability of ELKS (and certainly allow for coding and testing on my part).
Thank you!
Hello @ghaerr,
Sorry for the really late reply! To try to answer some of your questions:
./fetch.sh
and ./build.sh
in build-ia16
to build and test everything on my end — including all the code for the MS-DOS and ELKS targets.
README.md
summarizes the process../build.sh
does not use DOSBox, but instead uses Andrew Jenner's bare-bones 86sim
emulator. 86sim
should probably also work on macOS.newlib-ia16
did — and still does — have some vestiges of code for targeting ELKS, though it is suffering from a bit of bit rot.
newlib-ia16
for ELKS really working again, we need to do at least these things:
<sys/errno.h>
to give ELKS error codes, not MS-DOS ones, when targeting ELKS_open
etc. to the reentrant _open_r
etc.Thank you!
Hello @tkchia,
Thank you very much for your explanation of build options, you provided a lot of information unknown to me.
And yes, some work is probably needed to get the scripts working on macOS.
Yes, indeed. It's likely going to need quite a bit of work, for instance none of the arguments passed to script
are implemented on macOS. Should I try to jump in and implement far pointer printf strings, it'd be lots easer on Linux.
(plus apparently lithoxs did not quite like Newlib's bloatedness).
Having got quite familiar with ELKS' C library over the last few years, I'd have to say it's smaller size and simplicity is probably better suited for ELKS at this point. ELKS doesn't need the multi-threaded nor multi-processor features either.
instead uses Andrew Jenner's bare-bones 86sim emulator. 86sim should probably also work on macOS.
86sim is a most interesting project!! It readily compiles on macOS. I have already extended it slightly to support a few more MSDOS system calls I ran into while testing some arbitrary .exe programs. I have also found a bug in the usage and meaning of 'loadSegment' internally. Are you at all interested in those modifications, or is your 86sim version only supposed to support the GCC regression tests?
I'm also thinking it could be quite straightforward to slightly rearrange 86sim to more easily support execution of ELKS applications directly. This could possibly prove useful for regression testing and/or debugging. Would you be interested in such an enhancement, or should something like this live in its own repository outside of reenigne and/or gcc-ia16?
Thank you!
Hello @ghaerr,
I'm also thinking it could be quite straightforward to slightly rearrange 86sim to more easily support execution of ELKS applications directly. This could possibly prove useful for regression testing and/or debugging. Would you be interested in such an enhancement, or should something like this live in its own repository outside of reenigne and/or gcc-ia16?
Yes, I am interested in this (and other patches). :slightly_smiling_face: I am not sure if Mr. Jenner might be interested in any further patches — I think he has other plans for his repository — but I will be glad to accept your changes.
Thank you!
Hello @tkchia,
I've started an 86sim fork from your and Andrew Jenner's project, which has initial support for ELKS a.out executables and also continues to load and run MZ executables. It doesn't implement many of the ELKS system calls yet, as the code being contained in a single .cpp file with large procedures makes for tough maintenance of all that.
I haven't yet decided whether to clean it up or what exactly to do with it yet. It seems there is a need for a very small 8086 emulator whose components (emulator, a.out/MZ executable header reading, system calls, etc) might be readily available for project experimentation or quick determination of code execution outside a native OS.
What 86sim lacks is a disassembler to see what is going on. Having that along with 86sim in a very few source files could make off-host debugging of various executable types a lot easier, it seems.
Have you seen Blinkenlights, a super nice text-mode-UI 8086 emulator for 8086 boot and other code? Ultimately, adding the ability to execute MSDOS or ELKS programs to that would be fantastic; unfortunately, it's build is tied heavily to the Actually Portable Executable project and is a complex build running on Linux only.
Thank you!
Hello @ghaerr,
I haven't yet decided whether to clean it up or what exactly to do with it yet. It seems there is a need for a very small 8086 emulator whose components (emulator, a.out/MZ executable header reading, system calls, etc) might be readily available for project experimentation or quick determination of code execution outside a native OS.
Well... if (and when) you decide that you would like me to merge in your changes, do let me know. :slightly_smiling_face:
Have you seen Blinkenlights, a super nice text-mode-UI 8086 emulator for 8086 boot and other code?
Well, I tried it a bit — and it definitely does look spiffy, though I am not sure about using it day to day. :slightly_smiling_face::slightly_smiling_face:
Thank you!
It might be worth to separate this into two issues:
An interesting, niche use-case I found for large model support would be adding gcc-ia16 to this small benchmark project I found.
Hello @tkchia,
Just a quick note to say I'm also interested in some way of using far pointers to strings with printf(). For now I've worked around it by copying the string data to a near string first, which is fine of course. The suggestion above (using %S) seems attractive as it'd be much cleaner if we could do printf("hello '%S'\n", farstring)
instead.
Thank you!
Hello! I just finished adapting Ralf Brown's AMITSRS to compile with gcc-ia16 and libi86. I had to copy the signature and description fields into an internal buffer of the program to make it work, using the libi86
_fmemcpy
function.This is part of a comment at the top of the source:
I assume this is needed to make
printf
accept far pointer strings for the%s
format. Because this memory model is not yet implemented by gcc-ia16 I tried using the%Fs
format string to accept far pointers. This appears to not be supported. So I finally settled on the intermediate buffer, which is fine here because the signatures and descriptions are of a known maximum length (80 bytes).