I'm compiling this C source with OpenWatcom V2 wcc
:
/* Writes a '\0'-terminated string to the file descriptor. */
static void fdputs(int fd, const char *s);
#pragma aux fdputs = \
"push si" \
"mov cx, -1" \
"repz scasb" \
"neg cx" \
"inc cx" /* now cx is the number of bytes to write */ \
"pop dx" /* now dx points to the buffer (s argument) */ \
"mov ah, 0x40" /* WRITE */ \
"int 0x21" \
parm [ bx si ] \
modify [ ax cx dx si ]; /* Also modifies cf */
int myfunc(void) {
fdputs(1, "Hello!");
return 0;
}
In the disassebly of the .obj file generated by wcc the 6 push
es and the 5 pop
s don't balance out. (The code, when run, crashes because of this.)
$ wcc -bt=dos -ms -s -os -W -w4 -wx -we -wcd=202 -0 -fr -fo=t.obj t.c
$ wdis -a -fi -i=@ t.obj
.387
PUBLIC myfunc_
EXTRN _small_code_:BYTE
DGROUP GROUP CONST,CONST2,_DATA
_TEXT SEGMENT BYTE PUBLIC USE16 'CODE'
ASSUME CS:_TEXT, DS:DGROUP, SS:DGROUP
myfunc_:
push bx
push cx
push dx
push si
mov ax,offset DGROUP:@$1
push ax
mov bx,1
xor si,si
push si
mov cx,0ffffH
repe scasb
neg cx
inc cx
pop dx
mov ah,40H
int 21H
xor ax,ax
pop si
pop dx
pop cx
pop bx
ret
_TEXT ENDS
CONST SEGMENT WORD PUBLIC USE16 'DATA'
@$1:
DB 48H, 65H, 6cH, 6cH, 6fH, 21H, 0
CONST ENDS
CONST2 SEGMENT WORD PUBLIC USE16 'DATA'
CONST2 ENDS
_DATA SEGMENT WORD PUBLIC USE16 'DATA'
_DATA ENDS
END
Am I using the wcc inline assembly correctly? Is this likely a bug in wcc?
I believe this is a bug with OpenWatcom C/C++, as I have observed this behaviour in the past. To get around it I list each parameter separately between their own
[
and]
. Try modifying:to be:
The resulting code should look like:
The use of the AX register to transfer the address of the
const char *s
is removed as well as the extrapush ax
that doesn't have a correspondingpop
associated with it.