Hello all,
I am experimenting with OpenWatcom, trying to compile a simple C
file into a COM executable. The tricky part is that I'd like to avoid
pulling in watcom's standard library and startup code in the process.
I have such TEST.C file:
void main(void) {
static char *hello = "Hello$";
_asm {
mov ah, 9
mov dx, hello
int 0x21
}
}
I filled TEST.LNK with the following directives:
FORMAT DOS COM
FILE test.obj
OPTION NODEFAULTLIBS
NAME TEST.COM
OPTION START=main_
I do get "something" out of this, but the binary file does not work
properly. The disassembled COM looks like that:
00000000 53 push bx
00000001 51 push cx
00000002 52 push dx
00000003 56 push si
00000004 57 push di
00000005 B409 mov ah,0x9
00000007 8B160C00 mov dx,[0xc] <-- this should be 0x11C
0000000B CD21 int 0x21
0000000D 5F pop di
0000000E 5E pop si
0000000F 5A pop dx
00000010 59 pop cx
00000011 5B pop bx
00000012 C3 ret
00000013 004865 add [bx+si+0x65],cl
00000016 6C insb
00000017 6C insb
00000018 6F outsw
00000019 2400 and al,0x0
0000001B 0004 add [si],al <-- this should be 0x114
0000001D 00 db 0x00
It appears that the COM file is not being originated at offset 0x100,
despite the "FORMAT DOS COM" wlink directive. It's also not
0-originated, so I am not sure how the offsets are calculated exactly.
Once I fix them with a hex editor, the executable works.
void main(void) {
static char *hello = "Hello$";
_asm {
mov ah, 9
mov dx, hello
int 0x21
}
}
The `hello` from `mov dx, hello` in assembly's perspective, means the
content of the variable. Not its address.
FORMAT DOS COM
FILE test.obj
OPTION NODEFAULTLIBS
NAME TEST.COM
OPTION START=main_
I'm not familiar with Watcom linker, but the linker user's guide says
to use these:
system com
If you disassembed a binary using a blind disassembler (which don't
know binary file format, and platform), all file bytes will be
treated as code, and will start at zero or at disassembler
application's predefined address.
Also check the compiled binary. Make sure it doesn't start with "MZ",
looking for a way of building minimalist COM files using the C
language, hoping that Open Watcom would be able
Hello all,
I am experimenting with OpenWatcom, trying to compile a simple C
file into a COM executable. The tricky part is that I'd like to avoid pulling in watcom's standard library and startup code in the process.
I have such TEST.C file:
void main(void) {
static char *hello = "Hello$";
_asm {
mov ah, 9
mov dx, hello
int 0x21
}
}
I compile it into an object and pass to wlink using these commands:
wcc -0 -ms -od -s -d0 -zl -zls test.c
wlink @TEST.LNK
I filled TEST.LNK with the following directives:
FORMAT DOS COM
FILE test.obj
OPTION NODEFAULTLIBS
NAME TEST.COM
OPTION START=main_
I do get "something" out of this, but the binary file does not work properly. The disassembled COM looks like that:
00000000 53 push bx
00000001 51 push cx
00000002 52 push dx
00000003 56 push si
00000004 57 push di
00000005 B409 mov ah,0x9
00000007 8B160C00 mov dx,[0xc] <-- this should be 0x11C
0000000B CD21 int 0x21
0000000D 5F pop di
0000000E 5E pop si
0000000F 5A pop dx
00000010 59 pop cx
00000011 5B pop bx
00000012 C3 ret
00000013 004865 add [bx+si+0x65],cl
00000016 6C insb
00000017 6C insb
00000018 6F outsw
00000019 2400 and al,0x0
0000001B 0004 add [si],al <-- this should be 0x114
0000001D 00 db 0x00
It appears that the COM file is not being originated at offset 0x100, despite the "FORMAT DOS COM" wlink directive. It's also not
0-originated, so I am not sure how the offsets are calculated exactly.
Once I fix them with a hex editor, the executable works.
What am I missing here?
I filled TEST.LNK with the following directives:...
OPTION START=main_
00000007 8B160C00 mov dx,[0xc] <-- this should be 0x11C
0000001B 0004 add [si],al <-- this should be 0x114
If you make your own startup code with proper
----8<----
org 100h
_cstart_:
...
end _cstart_
----8<----
It may just work.
OPTION START=main_
A COM file *always* starts at 0x0100. Maybe this directive
interferes with it ?
00000007 8B160C00 mov dx,[0xc] <-- this should be
0x11C
the 0xC is almost the offset from that commands address to the string
(off by one). IOW, it looks like the resolving (by "wlink") didn't
quite kick in. Maybe the linker needs to be told that it is
converting a COM style program too ?
0000001B 0004 add [si],al <-- this should be 0x114
AFAIKS everything from address 0x1A is beyond your code/program.
IOW, no idea what the remark is about.
A COM file *always* starts at 0x0100. Maybe this directive
interferes with it ?
Without "OPTION START" the result is exactly the same, with the only >difference that wlink complains about "no starting address found".
0000001B 0004 add [si],al <-- this should be 0x114
AFAIKS everything from address 0x1A is beyond your code/program.
IOW, no idea what the remark is about.
You are correct that 0x1B is beyond code, but it is not beyond data.
My understanding is that the "04 00" value starting at 1Ch is a near
pointer that is supposed to be loaded by mov dx,[0x0c]
How the values 0x000C and 0x0004 have been computed exactly, this
I have no idea.
dn. Wed, 2 Aug 2023 20:28:34 -0700 (PDT), Alexei A. Frounze napisał:
If you make your own startup code with properIs org 100h really required in this context? Isn't it the job of the
----8<----
org 100h
_cstart_:
...
end _cstart_
----8<----
It may just work.
linker to compute proper addresses?
I tried nonetheless, but nasm does not understand the "org" directive
when using the -f obj target. It's apparently only valid for -f bin.
00000000 53 push bx...
Could you add a command like "lea ax,main" and see which address
"main" gets translated too ? It should ofcourse show 0x0100. If it
does not not than the linker didn't generate a COM style file to
begin with.
Also, have you checked the binary contents of your (supposed) .COM
file ? If it starts with "MZ" ...
It appears that without startup code, wlink simply won't generate
a proper COM.
I noticed that you are compiling with the "-ms" switch
(small memory model), which is incompatible with a COM style
executable. Try "-mt" (tiny memory model) instead.
Try "-mt" (tiny memory model) instead.
"-ms" is the proper switch for compiling object files for COM
executables. In fact, the wcc compiler doesn't even understand -mt.
Building a COM itself is well documented and hence easy to achieve.
The problem here is that I was trying to make Open Watcom build a tiny
(as in "very small") COM file by avoiding Watcom's libc and startup code,
Then the COM file indeed becomes very small, but it also ceases working,
as the generated code seems to expect to be executed within an environment prepared by Watcom's startup routines.
Thats too bad. At least you can't say I didn't try. :-)
Strange. Being able to specify a DOS COM output, but not actually
getting it. :-\
It appears that the COM file is not being originated at offset 0x100,
despite the "FORMAT DOS COM" wlink directive. It's also not
0-originated, so I am not sure how the offsets are calculated exactly.
Once I fix them with a hex editor, the executable works.
What am I missing here?
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 415 |
Nodes: | 16 (2 / 14) |
Uptime: | 55:27:51 |
Calls: | 8,728 |
Calls today: | 1 |
Files: | 13,276 |
Messages: | 5,958,506 |