Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

ASM or C? The age old questions. And a request for ACPI pointers

38 views
Skip to first unread message

Kristoffer

unread,
Feb 8, 2013, 7:47:50 AM2/8/13
to
So I'm well underway and learning the quirks of good ol long mode...

I've traditionally thought you write kernel code in C. Maybe I'm
getting old and sadistic, but I find myself having to work around the
compiler more than the advantage of being able to express complex logic
easily seems to offer. So I've restarted, after all there is no
timeline or rush. All in assembly on Windoze. So far so good. I also
figured out the Bochs graphical debugger. Niiiice.

So that brings me to part 2.

Part of my kernel from early on involves the ability to do real mode
interrupts. They are controlled obviously, but things like graphics
modes, and not even writing a legacy floppy driver, just int 13ing it
would be nice so I can concentrate on modern hardware. As such
interrupt mapping and remapping has to occur. In the past I have used
the 8259 chips. Now the defacto standard is the ACPI interface. All of
the documentation I find is either too much to weed through, or assumes
you already know all about it. Is there any good tutorials, maybe even
with some pseudo working code that go over the Local APIC timer and
interrupt remapping? I'd like to avoid falling back on legacy chipsets
if at all possible.

TIA

Chris

James Harris

unread,
Feb 8, 2013, 12:38:02 PM2/8/13
to
On Feb 8, 12:47 pm, Kristoffer <kris...@85138.tk> wrote:
> So I'm well underway and learning the quirks of good ol long mode...
>
> I've traditionally thought you write kernel code in C.  Maybe I'm
> getting old and sadistic, but I find myself having to work around the
> compiler more than the advantage of being able to express complex logic
> easily seems to offer.

I have found similar. Having got used to writing in assembly I find
that C - or maybe the compilers I have tried - tend to get in the way
of what I have been trying to do.

Assembly is required (sic) for at least some of the kernel so it is
not possible to avoid assembly. It is, however, possible to avoid use
of HLL in the privileged code. Maybe all of this part of an OS could
be coded in assembly. The kernel should be small anyway, eh? C is
probably needed for Linux as it is monolithic.

A HLL would be ideal for the system utilities though in an environment
provided by the OS kernel.

Of course, the kernel could be a mix of assembly and C but I find the
interfacing between assembly and C to be frustrating. Compilers cannot
usually adapt their calling conventions much. This means that the
assembly side always has to change or at least conform to include the
interfacing code - and that if I change compiler I have to change the
assembly code. That shouldn't be the case.

Of the compilers I have tried Open Watcom seems to allow a lot of
customisations of the calling mechanisms. However, it seems to require
me to write non-standard C. If I write in C I want it to be completely
standard C. Maybe I haven't learned enough about different compilers
but I would have thought it best to have standard C source code and
have ways to tell the compiler how to interface to different modules.

Anyway, the jury is still out. I have been looking at 16-bit C and
assembly which makes things worse because of the different pointer
modules. 32-bit or 64-bit should be a bit easier.


> So I've restarted, after all there is no
> timeline or rush.  All in assembly on Windoze.  So far so good.  I also
> figured out the Bochs graphical debugger.  Niiiice.

Is that stuff documented anywhere? If not, would you be willing to
write up what you got worked out? I might try Bochs at some point.

>
> So that brings me to part 2.
>
> Part of my kernel from early on involves the ability to do real mode
> interrupts.  They are controlled obviously, but things like graphics
> modes, and not even writing a legacy floppy driver, just int 13ing it
> would be nice so I can concentrate on modern hardware.

I am not sure I understand that last sentence.

> As such
> interrupt mapping and remapping has to occur.  In the past I have used
> the 8259 chips.  Now the defacto standard is the ACPI interface.

Do you mean APIC? It seems to fit your comments better but there is
also an ACPI standard. (See http://www.acpi.info/.)

> All of
> the documentation I find is either too much to weed through, or assumes
> you already know all about it.  Is there any good tutorials, maybe even
> with some pseudo working code that go over the Local APIC timer and
> interrupt remapping?  I'd like to avoid falling back on legacy chipsets
> if at all possible.

For the APICs how about

http://wiki.osdev.org/APIC

IIRC I read somewhere that using the APIC architecture can require a
lot of work to route or remap interrupts - and deal with edge vs level
triggering - and that such work is not needed if one sticks with the
PIC. Something to be aware of before you commit to APIC - unless you
need it for 64-bit mode.

James

Kristoffer

unread,
Feb 8, 2013, 4:08:31 PM2/8/13
to
I've always been a gcc fan. I've been on *nix systems professionally
for over 13 years and the system compiler on commerical Unices is always
a little weird, but its usually only there to bootstrap a gcc build.
Gcc is fairly predictable, and a close look at the Linux source you can
see a _LOT_ of things rely on gcc's behavior. However, a lot of their
metrics have changed with 64 bit code. Variables arent passed in on the
stack anymore unless the function is variadic, and with 16 GP registers
to play with it can get a little confusing. I find my own code still
trying to do gymnastics to squeeze everything into the few registers I
am used to dealing with. Once I get into some more complex code though,
I think I will enjoy it much better having the elbow room.
>
>> So I've restarted, after all there is no
>> timeline or rush. All in assembly on Windoze. So far so good. I also
>> figured out the Bochs graphical debugger. Niiiice.
>
> Is that stuff documented anywhere? If not, would you be willing to
> write up what you got worked out? I might try Bochs at some point.
>
http://wiki.osdev.org/Bochs

Scroll down to "gui debugger" - Its pretty easy to turn on, but for some
reason not documented in the bochs manual anywhere.
>>
>> So that brings me to part 2.
>>
>> Part of my kernel from early on involves the ability to do real mode
>> interrupts. They are controlled obviously, but things like graphics
>> modes, and not even writing a legacy floppy driver, just int 13ing it
>> would be nice so I can concentrate on modern hardware.
>
> I am not sure I understand that last sentence.
>
>> As such
>> interrupt mapping and remapping has to occur. In the past I have used
>> the 8259 chips. Now the defacto standard is the ACPI interface.
>
> Do you mean APIC? It seems to fit your comments better but there is
> also an ACPI standard. (See http://www.acpi.info/.)
>
Yeah typo. What I meant was I'm not going to worry about a floppy
driver or IDE, but concetrate on newer hardware which seems to be more
standardized.
>> All of
>> the documentation I find is either too much to weed through, or assumes
>> you already know all about it. Is there any good tutorials, maybe even
>> with some pseudo working code that go over the Local APIC timer and
>> interrupt remapping? I'd like to avoid falling back on legacy chipsets
>> if at all possible.
>
> For the APICs how about
>
> http://wiki.osdev.org/APIC
>
> IIRC I read somewhere that using the APIC architecture can require a
> lot of work to route or remap interrupts - and deal with edge vs level
> triggering - and that such work is not needed if one sticks with the
> PIC. Something to be aware of before you commit to APIC - unless you
> need it for 64-bit mode.
>
> James
>
Yeah I agree, it seems to be a nightmare to program. I'll stick with
the 8259 and worry about it if one day I want to support multi-core /
multiple processors.

Alexei A. Frounze

unread,
Feb 8, 2013, 4:39:13 PM2/8/13
to
On Feb 8, 9:38 am, James Harris <james.harri...@gmail.com> wrote:
> On Feb 8, 12:47 pm, Kristoffer <kris...@85138.tk> wrote:
>
> > So I'm well underway and learning the quirks of good ol long mode...
>
> > I've traditionally thought you write kernel code in C.  Maybe I'm
> > getting old and sadistic, but I find myself having to work around the
> > compiler more than the advantage of being able to express complex logic
> > easily seems to offer.
>
> I have found similar. Having got used to writing in assembly I find
> that C - or maybe the compilers I have tried - tend to get in the way
> of what I have been trying to do.

How so? Examples?!

...

> Of course, the kernel could be a mix of assembly and C but I find the
> interfacing between assembly and C to be frustrating. Compilers cannot
> usually adapt their calling conventions much. This means that the
> assembly side always has to change or at least conform to include the
> interfacing code - and that if I change compiler I have to change the
> assembly code. That shouldn't be the case.

I think this is the wrong approach. If you're using C and assembly, it
makes sense to do most in C (preferably, in standard C) and in
assembly only the parts that can't be done in C (e.g. accesses to
system registers, segment registers, etc etc). If you're writing
assembly code, it's already custom. Make it a tad more custom, suit it
to the C compiler, not the other way around.

> Of the compilers I have tried Open Watcom seems to allow a lot of
> customisations of the calling mechanisms. However, it seems to require
> me to write non-standard C. If I write in C I want it to be completely
> standard C. Maybe I haven't learned enough about different compilers
> but I would have thought it best to have standard C source code and
> have ways to tell the compiler how to interface to different modules.

You're doing something wrong, if you think the compiler is forcing you
to write non-standard C code. Perhaps, you're trying to do in C
something that truly belongs to assembly code?

> Anyway, the jury is still out. I have been looking at 16-bit C and
> assembly which makes things worse because of the different pointer
> modules. 32-bit or 64-bit should be a bit easier.

What pointer modules?

Are you mixing near and far pointers in your C code?

Btw, by choosing one of the available memory models you can make your
C pointers (code and data independently):
- near (16-bit offsets only)
- far (16-bit segment + 16-bit offset)
- huge (32-bit)
I don't know exactly how huge pointers are implemented (as far or as
32-bit physical addresses), but they have the advantage that you can
add to them indices larger than 64KB using regular pointer arithmetic
in C. This may alleviate some of your problems.

Also, it may be a good idea to keep 16-bit parts of the system as
small and simple as possible, so you don't need to wrestle with the
various limitations of the 16-bit underworld.

Alex

Kristoffer

unread,
Feb 8, 2013, 6:56:05 PM2/8/13
to
Alex, I think James and I are on two different wavelengths compiler
wise. I'm used to how gcc handled 32 bit code, but I'm not familiar
with the semantics 64 bit code seems to take and for the few things,
interrupt gates, loading cr3, etc.. its becoming a bear. Not to mention
something simple like

struct {
unsigned short size;
unsigned long addr;
} IDTR __attribute__((__packed__));

void load_idt()
{
asm("lidt (%0)"::"p"(&IDTR));
}

ended up doing something with RIP that wouldnt assemble. I eventually
figured it out, but I'm starting to enjoy my ASM better.

If I were writing this commercially hell yeah I'd use C, but for my own
thought process, ASM works better.

Rod Pemberton

unread,
Feb 8, 2013, 7:44:37 PM2/8/13
to
"Kristoffer" <kri...@85138.tk> wrote in message
news:D5Gdnc5fKaxtbonM...@giganews.com...
> So I'm well underway and learning the quirks of good ol long
> mode...
>
> I've traditionally thought you write kernel code in C. Maybe
> I'm getting old and sadistic, but I find myself having to work
> around the compiler more than the advantage of being able
> to express complex logic easily seems to offer.

You just stated why modern C compilers have "intrinsics" for x86
instructions ...

> [...]
> So that brings me to part 2.
>
> Part of my kernel from early on involves the ability to do real
> mode interrupts. They are controlled obviously, but things like
> graphics modes, and not even writing a legacy floppy driver,
> just int 13ing it would be nice so I can concentrate on modern
> hardware.

My OS doesn't use RM or BIOS. I didn't get to developing IDE
code, before I moved on to non-OS projects.

> As such interrupt mapping and remapping has to
> occur. In the past I have used the 8259 chips. Now the defacto
> standard is the ACPI interface. All of the documentation I find
> is either too much to weed through, or assumes you already
> know all about it. Is there any good tutorials, maybe even with
> some pseudo working code that go over the Local APIC timer
> and interrupt remapping? I'd like to avoid falling back on
> legacy chipsets if at all possible.

Sorry, I've not gotten to LAPIC, and I didn't intend to ever do
so. I.e., I only planned on using historical features originally,
which is now called legacy support and won't be around much
longer... sigh. I could probably locate standard "obtuse"
documentation.


Rod Pemberton


Rod Pemberton

unread,
Feb 8, 2013, 7:47:35 PM2/8/13
to
"Kristoffer" <kri...@85138.tk> wrote in message
news:ZdadnaJcx-sTDYjM...@giganews.com...
...

> I'm used to how gcc handled 32 bit code, but I'm not familiar
> with the semantics 64 bit code seems to take and for the few
> things, interrupt gates, loading cr3, etc.. its becoming a bear.
> Not to mention something simple like
>
> struct {
> unsigned short size;
> unsigned long addr;
> } IDTR __attribute__((__packed__));
>
> void load_idt()
> {
> asm("lidt (%0)"::"p"(&IDTR));
> }
>
> ended up doing something with RIP that wouldnt assemble. I
> eventually figured it out, but I'm starting to enjoy my ASM
> better.
>
> If I were writing this commercially hell yeah I'd use C, but for
> my own thought process, ASM works better.

Should that "p" be an "m" ... ?


My code for lidt in C is:

void asm_lidt(idt_pointer idtp)
{
#ifdef __DJGPP__
__asm__ (
"lidt %0\n"
: /* no output */
:"m" (idtp)
);
#endif
#ifdef __WATCOMC__
_asm {
.386p
lidt fword ptr idtp
.386
}
#endif
}

It's called like any other C function:

asm_lidt(idtp);

I basically did almost all of my assembly that way, mostly as
single instructions. The exception is code for interrupt wrappers
and OS startup code which are longer routines. The rest is C.

idt_pointer is just typedef'd struct with the correct layout. The
declaration of idtp allocates an actual struct. I use the
compiler directives "#pragma pack(push,1)" and "#pragma pack(pop)"
for alignment. Both OW and DJGPP support "#pragma pack" and it
gets rid of all those __attribute__()'s or __declspec()'s. I.e.,
the code becomes closer to ANSI etc.

I do have a note that DJGPP and OW are generating differently
sized offsets for the lidt instruction in asm_lidt(). Apparently,
I never got around to finding or fixing that, not that it's
critical, just inconsistent.


Rod Pemberton


James Harris

unread,
Feb 13, 2013, 7:26:52 AM2/13/13
to
On Feb 8, 9:39 pm, "Alexei A. Frounze" <alexfrun...@gmail.com> wrote:

...

> > > I've traditionally thought you write kernel code in C.  Maybe I'm
> > > getting old and sadistic, but I find myself having to work around the
> > > compiler more than the advantage of being able to express complex logic
> > > easily seems to offer.
>
> > I have found similar. Having got used to writing in assembly I find
> > that C - or maybe the compilers I have tried - tend to get in the way
> > of what I have been trying to do.
>
> How so? Examples?!

How long have you got...? :-(

> > Of course, the kernel could be a mix of assembly and C but I find the
> > interfacing between assembly and C to be frustrating. Compilers cannot
> > usually adapt their calling conventions much. This means that the
> > assembly side always has to change or at least conform to include the
> > interfacing code - and that if I change compiler I have to change the
> > assembly code. That shouldn't be the case.
>
> I think this is the wrong approach. If you're using C and assembly, it
> makes sense to do most in C (preferably, in standard C) and in
> assembly only the parts that can't be done in C (e.g. accesses to
> system registers, segment registers, etc etc). If you're writing
> assembly code, it's already custom. Make it a tad more custom, suit it
> to the C compiler, not the other way around.

From a high level I would agree. In practice, though, I'm no longer
sure. If I wrote something in C I wouldn't want to tie myself to a
specific compiler. C should be C, IMHO, not custom C. ISTM I should be
able to change compiler without having to change any assembly code the
C interfaces with. Surely a compiler should be able to adapt its code
to suit the libraries it is using. A compiler is a code generator
after all.

Perhaps another way of looking at this, because of the tie-in to a
particular compiler, is to use assembly to provide an environment for
C to run in - including providing calls for system functions like
special register changes - and then let the C code run as an entity. I
have become a bit disillusioned about the idea of writing a single app
in multiple languages.

> > Of the compilers I have tried Open Watcom seems to allow a lot of
> > customisations of the calling mechanisms. However, it seems to require
> > me to write non-standard C. If I write in C I want it to be completely
> > standard C. Maybe I haven't learned enough about different compilers
> > but I would have thought it best to have standard C source code and
> > have ways to tell the compiler how to interface to different modules.
>
> You're doing something wrong, if you think the compiler is forcing you
> to write non-standard C code. Perhaps, you're trying to do in C
> something that truly belongs to assembly code?

Don't forget this is 16-bit code. Open Watcom has *lots* of non-
standard features to support it. In fairness I could probably omit
most of them but some like the "far" keyword might remain. Also, I
found its name mangling annoying. IIRC some labels have an underscore
appended. Others have an underscore prepended. This is all fine for C
talking to C in the same compiler but I don't like the way the
compiler goes its own way and expects anything interfacing with it to
change.

> > Anyway, the jury is still out. I have been looking at 16-bit C and
> > assembly which makes things worse because of the different pointer
> > modules. 32-bit or 64-bit should be a bit easier.
>
> What pointer modules?

Sorry. I think I meant pointer "modes" - i.e. near and far. I had been
thinking about coding 16-bit programs in modules.

> Are you mixing near and far pointers in your C code?

Yes. That's maybe a nub of the issue. I would want to write the C code
and *not* have the code itself specify pointer types but to just
specify a pointer. IMHO the compiler should generate the correct type
of pointer to suit its use, taking into account any relevant factors.

> Btw, by choosing one of the available memory models you can make your
> C pointers (code and data independently):
> - near (16-bit offsets only)
> - far (16-bit segment + 16-bit offset)
> - huge (32-bit)
> I don't know exactly how huge pointers are implemented (as far or as
> 32-bit physical addresses), but they have the advantage that you can
> add to them indices larger than 64KB using regular pointer arithmetic
> in C. This may alleviate some of your problems.

Thanks. I saw some info about huge pointers - updated by subroutine
call, IIRC, so that they remain valid on carry from the low 16 bits.

> Also, it may be a good idea to keep 16-bit parts of the system as
> small and simple as possible, so you don't need to wrestle with the
> various limitations of the 16-bit underworld.

What I am writing at the mo is a purely 16-bit piece of code. It will
start small, for sure, and may not get very large. However, I wanted
to allow for it to grow in case it needed to. I thought to write the
code (whether C or assembly or a mixture of both) into modules which
each had less than 64k code.

I still want to write it in modular form. Am trying out some ideas
before I commit to one particular way of coding it.

James

Alexei A. Frounze

unread,
Feb 15, 2013, 7:51:05 AM2/15/13
to
On Feb 13, 4:26 am, James Harris <james.harri...@gmail.com> wrote:
> On Feb 8, 9:39 pm, "Alexei A. Frounze" <alexfrun...@gmail.com> wrote:
>
> ...
>
> > > > I've traditionally thought you write kernel code in C.  Maybe I'm
> > > > getting old and sadistic, but I find myself having to work around the
> > > > compiler more than the advantage of being able to express complex logic
> > > > easily seems to offer.
>
> > > I have found similar. Having got used to writing in assembly I find
> > > that C - or maybe the compilers I have tried - tend to get in the way
> > > of what I have been trying to do.
>
> > How so? Examples?!
>
> How long have you got...? :-(

I've got some.
Write straight C code wherever possible. If you bump into a limitation
of the compiler or of the environment (e.g. those ugly segments or
special CPU registers inaccessible from C), write helper routines in
assembly to handle those situations. That's all you need.

Say, you're making a C program using 16-bit/near pointers but you want
to access the entire megabyte. What do you do? You write a few
assembly routines to take the physical address and the value (if it's
a memory write) and do just that. If you want to reuse this code with
a different compiler, you may need to rewrite the assembly bits. If
you want to reuse the code in 32-bit mode, you may actually #define
(under #if) WRITE_MEMORY_BYTE(ADDR, VAL) to expand to either a call to
the assembly function or to *(unsigned char*)(ADDR) = (VAL).

> > > Of the compilers I have tried Open Watcom seems to allow a lot of
> > > customisations of the calling mechanisms. However, it seems to require
> > > me to write non-standard C. If I write in C I want it to be completely
> > > standard C. Maybe I haven't learned enough about different compilers
> > > but I would have thought it best to have standard C source code and
> > > have ways to tell the compiler how to interface to different modules.
>
> > You're doing something wrong, if you think the compiler is forcing you
> > to write non-standard C code. Perhaps, you're trying to do in C
> > something that truly belongs to assembly code?
>
> Don't forget this is 16-bit code. Open Watcom has *lots* of non-
> standard features to support it. In fairness I could probably omit
> most of them but some like the "far" keyword might remain. Also, I
> found its name mangling annoying. IIRC some labels have an underscore
> appended. Others have an underscore prepended. This is all fine for C
> talking to C in the same compiler but I don't like the way the
> compiler goes its own way and expects anything interfacing with it to
> change.

I don't think that "far" has to remain. I haven't tried it with OW,
but with Turbo C plain pointers become far or huge if you use the
appropriate command-line switch to choose the relevant memory model.
OW probably has an option to choose the default calling convention,
which may help getting around the various name manipulations and help
keeping the code free of __cdecl, __stdcall and __fastcall things.
Check it out.

> > > Anyway, the jury is still out. I have been looking at 16-bit C and
> > > assembly which makes things worse because of the different pointer
> > > modules. 32-bit or 64-bit should be a bit easier.
>
> > What pointer modules?
>
> Sorry. I think I meant pointer "modes" - i.e. near and far. I had been
> thinking about coding 16-bit programs in modules.

You can do that too. There are options.

> > Are you mixing near and far pointers in your C code?
>
> Yes. That's maybe a nub of the issue. I would want to write the C code
> and *not* have the code itself specify pointer types but to just
> specify a pointer. IMHO the compiler should generate the correct type
> of pointer to suit its use, taking into account any relevant factors.

Research the compiler's options. I believe you can find all that's
needed for that.

> > Btw, by choosing one of the available memory models you can make your
> > C pointers (code and data independently):
> > - near (16-bit offsets only)
> > - far (16-bit segment + 16-bit offset)
> > - huge (32-bit)
> > I don't know exactly how huge pointers are implemented (as far or as
> > 32-bit physical addresses), but they have the advantage that you can
> > add to them indices larger than 64KB using regular pointer arithmetic
> > in C. This may alleviate some of your problems.
>
> Thanks. I saw some info about huge pointers - updated by subroutine
> call, IIRC, so that they remain valid on carry from the low 16 bits.
>
> > Also, it may be a good idea to keep 16-bit parts of the system as
> > small and simple as possible, so you don't need to wrestle with the
> > various limitations of the 16-bit underworld.
>
> What I am writing at the mo is a purely 16-bit piece of code. It will
> start small, for sure, and may not get very large. However, I wanted
> to allow for it to grow in case it needed to. I thought to write the
> code (whether C or assembly or a mixture of both) into modules which
> each had less than 64k code.
>
> I still want to write it in modular form. Am trying out some ideas
> before I commit to one particular way of coding it.

In the olden days of DOS, big programs used what's called overlays.
Basically, they were split into independent modules (possibly no
larger than 64K, but I'm not sure) that could be brought into memory
on demand and so the program would either use less memory or would be
able to be bigger than some 500K. This works particularly well with
code as it does not change and needs not to be written back to the
disk.

Alex

James Harris

unread,
Feb 15, 2013, 1:53:35 PM2/15/13
to
On Feb 15, 12:51 pm, "Alexei A. Frounze" <alexfrun...@gmail.com>
wrote:

...

> > > > I have found similar. Having got used to writing in assembly I find
> > > > that C - or maybe the compilers I have tried - tend to get in the way
> > > > of what I have been trying to do.
>
> > > How so? Examples?!
>
> > How long have you got...? :-(
>
> I've got some.

An offer of help? My comment was idiomatic to hint that I had had a
long list of issues of trying to get a compiler to do what I want. Am
not sure if you took it that way but I could mention some issues.

Here's one. Take the following C code.

/*
* Test of minimum code
*/

/* Build with
* wcc -ml t5.c
* wlink sys dos name t5 file t5.obj
*/

int main()
{
return 7;
}

This is about as simple as it could be. Even so, before it gets to the
body of the program the resulting file, t5.exe, makes calls to DOS.
This happens before I would get control. As this code is to run on
bare BIOS DOS interrupts (int 0x21) will not be available so the
generated code is useless.

I can think of a number of potential causes and fixes: start in
assembly, different build process, do the linking myself but which
ones are likely to be most productive....? Have looked at the first
two. No solutions yet.

...

> I don't think that "far" has to remain. I haven't tried it with OW,
> but with Turbo C plain pointers become far or huge if you use the
> appropriate command-line switch to choose the relevant memory model.
> OW probably has an option to choose the default calling convention,
> which may help getting around the various name manipulations and help
> keeping the code free of __cdecl, __stdcall and __fastcall things.
> Check it out.

OK am trying different compile and link options.

...

> > > Are you mixing near and far pointers in your C code?
>
> > Yes. That's maybe a nub of the issue. I would want to write the C code
> > and *not* have the code itself specify pointer types but to just
> > specify a pointer. IMHO the compiler should generate the correct type
> > of pointer to suit its use, taking into account any relevant factors.
>
> Research the compiler's options. I believe you can find all that's
> needed for that.

There are certainly lots of options with Open Watcom compiler and
linker - and lots of disparate documents about it. Some apparent
contradictions. For example, with wlink am not too clear as to when to
use "sys" and when to use "form". Some sources of info refer to one,
some to the other.

A lot of the issues may well be to do with not yet knowing enough
about OW but there is a lot of it to learn and, as when considering
anything new, it is reasonable to consider whether to invest the time
needed to learn package X or package Y. OW is certainly complex.

BCC (Bruce's C Compiler, not Borland's) also seems good. It is much
simpler than OW but where OW has loads of documentation BCC seems to
have almost none other than the man page.

BCC can generate an executable as a 64k code segment and a 64 data
segment. From tests, I cannot get it to natively access more than 64k
at a time. I might be able to use it to produce 64k modules but am not
sure yet how I would link them.

James

Rod Pemberton

unread,
Feb 16, 2013, 8:20:55 AM2/16/13
to
"James Harris" <james.h...@gmail.com> wrote in message
news:77dd8763-04cf-4ec9...@g8g2000vbf.googlegroups.com...

...

> Here's one. Take the following C code.
>
> /*
> * Test of minimum code
> */
>
> /* Build with
> * wcc -ml t5.c
> * wlink sys dos name t5 file t5.obj
> */
>
> int main()
> {
> return 7;
> }
>
> This is about as simple as it could be. Even so, before
> it gets to the body of the program the resulting file, t5.exe,
> makes calls to DOS.

Yes.

> This happens before I would get control.

Yes.

> As this code is to run on bare BIOS ...

Ok.

> ... DOS interrupts (int 0x21) will not be available ...

True.

FYI, the BIOS does usually set this vector to something. Even
so, it won't be a DOS Int 0x21. It might also not be a valid or
useable BIOS vector either, just that it gets set.

> ... so the generated code is useless.

No! Wrong conclusion.

The obj code for the C code above is clean. Disassemble the obj
('wdis' or 'objdump'). As written, it doesn't call any DOS
function (or shouldn't...). It's the stub or crt.o or DOS startup
code for the linked exe that is calling DOS... Yes, some C code,
in the C library, mostly I/O related code, calls DOS or the BIOS.

> There are certainly lots of options with Open Watcom
> compiler and linker - and lots of disparate documents
> about it. Some apparent contradictions. For example,
> with wlink am not too clear as to when to use "sys" and
> when to use "form". Some sources of info refer to
> one, some to the other.

You may have to connect to news.openwatcom.org and post there.
Posting through AIOE.org or any other Usenet provider won't
propagate back to OW's newserver. Messages will be sent out
though. At least, that was how it worked some years ago.

For the OW version I'm using, the documentation was in some
special format (*.IHP). I had to run all the manuals through some
script to convert the documentation to text. Now, I can grep them
(available via DJGPP). Linker options are in LGUIDE.TXT for this
version. For the version you're using, I'd hope that they
converted the documentation to text or pdf files.

One of wlink's "option" options for all executable types is
"NODefaultlibs". That should eliminate the default libraries.

One of wlink's "option" options for Windows, Windows NT, OS/2,
DOS/4G executables is "STUB='stub_name'". This option allows you
to place your own startup code on the executable at it's start. I
think the stub has to be a valid 16-bit DOS exe, but I'm not 100%
sure about that. At this point in time, I have no idea about how
to transfer from the stub to the main executable. Of course,
you're not wanting a DOS .exe stub ... BUT, you may be able to
throw a Multiboot header into that stub, or some other bootloader
setup. That might work. Also, Alexei has code on his website to
boot DOS .exe's, IIRC. That might work or be useable somehow too.

Alexei mentioned pointers. Many C compilers can correctly convert
addresses to a pointer via a cast. For situations where that
doesn't work, the compilers have various methods to produce
"special" pointers. Typically, these are either macro's, or
functions. OW prefers macro's. E.g., 16-bit OW has:
MK_FP(),FP_SEG(),FP_OFF(). It also has far pointers etc. These
are described in CLIB.TXT and CGUIDE.TXT for this version. 32-bit
OW is slightly different. 32-bit DJGPP is very different.


Rod Pemberton



0 new messages