Open crazii opened 7 months ago
asm block use C preprocessor tokenizing and C language tokens that ';' character should be end of statement. Comment should be standard C comment. If it doesn't work as expected then give here sample code.
Testing code:
#define TEST(reg) \
push reg; \
pop reg;
int main()
{
__asm {
xchg ax, bx; //tag
TEST(ax);
xchg ax, bx; //tag
}
return 0;
}
WDIS output:
Segment: _TEXT BYTE USE16 00000016 bytes
0000 main_:
0000 B8 0C 00 mov ax,0x000c
0003 E8 00 00 call __STK
0006 53 push bx
0007 51 push cx
0008 52 push dx
0009 56 push si
000A 57 push di
000B 93 xchg ax,bx
000C 50 push ax
000D 93 xchg ax,bx
000E 31 C0 xor ax,ax
0010 5F pop di
0011 5E pop si
0012 5A pop dx
0013 59 pop cx
0014 5B pop bx
0015 C3 ret
Also __asm { pop ds; xchg ax, bx }
will get an error,
__asm { pop ds xchg ax, bx }
will generate only the LAST instruction.
Only (with a line break)
__asm { pop ds [;]
xchg ax, bx }
Works.
This also makes the define including __asm
keyword not working. (with or without ;
)
#define TEST() __asm {\
push ax[;] \
pop ax [;] \
}
Many Thanks for your detailed bug report info. The asm statement is not much used in OW source code. It uses #pragma aux. asm statement processing must be reviewed.
I checked how the __asm statement is processed by OW compilers. there are following limitation, it explains behaviour which you are reporting.
If you need using macros and multi statements line then best selection is to use #pragma aux. pragma aux process each string token as simple instruction that you can serialize many instruction as you want in single or multiple lines. pragma aux can combine bytes and instruction together and can use macros for any part of declaration.
Can it be used in another inline assembly? like it's nested - call/embed another #praga aux block in the existing #pragma aux
or __asm{}
Here's my original thoughts: I want reuse the hack for the offset, offered by @joncampbell123 from: here, for better maintenance, so that there will be only one copy in the original source and avoid typos/bugs among multiple copies.
#define HACK_OFFSET(reg, label) \
call hack; \
jmp label; \
hack: \
pop reg; \
push bx; \
mov bx, reg; \
add reg, word ptr cs:[bx+1]; \
add reg 3; \
pop bx
...
__asm {
...
#if defined(__BC__)
mov ax, offset LABEL
#else
HACK_OFFSET(ax, LABEL)
#endif
...
LABEL:
}
I don't have much experience with #pragma aux, so currently I don't think it's possible to do it with #pragma aux. Very much appreciated if you have any ideas/advices. Otherwise I think I have to stick with multiple copies among the source. - not perfect, but at least it's working.
DOSLIB also uses pragma aux if you want some examples:
https://github.com/joncampbell123/doslib/blob/master/hw/dos/dos.h#L133
Pragma aux has a lot more than just assembly language and is documented here: http://downloads.openwatcom.org/ftp/manuals/current/cguide.pdf
Thanks,
I understood that it can tell the compiler what input registers it use, what it returns, and what it modifies.
I've written some of them when wrap up 32bit mode dpmi functions in a DJGPP style https://github.com/crazii/USBDDOS/blob/master/USBDDOS/DPMI/dpmi_wc.c (a couple of years ago but now deprecated),
But that's the limit of my experience.
I read the cguide.pdf just now that #pragma aux indeed has much more options, mostly ABI related.
Anyways with hacks/workaounds my project of Open watcom build is OK and I just wanted to give some feedback to open watcom, hope it might help.
I'll leave this issue as a feature request, and with a question mark, whether/when to improve is up to you.
OK. The OW concept for pragma aux is that it is template of code, single definition and multiple use. Any code described by pragma aux represent C like function. You can define multiple parameters and single return value. power of pragma aux is in use of registers, stack can be used for passing parameters but is not eficient as registers. Any addressing is done in C code, you have no access to member of structure etc, but you can pass address by register to in-line code. You can see into bld/watcom/h subdirectory, there are many header files with in-line assembly they is included to C source code and code is used only if you instantized it by call. By example there is tinyio.h to direct access to DOS API calls from C source without int86 overhead. You can look on several file to better understand of use pragma aux. int10.h int33.h xfloat.h for FPU related code there are also lot assembly in-line code in C run-time library next example is C API for RDOS released by #pragma aux construct, it is in bld/watcom/h files owcomp.h, owflat.h and rdosdev.h. generaly it is used for small piece of assembly code which should be more efficient. Generaly OW concept is to do as much as possible in C and only improve code where it has sense by in-line assembly or if you need some interaction with HW from C code.
Generaly OW preferred method for in-line assembly is #pragma aux. __asm statement is not used in OW code base that it has low priority to do any enhancement. it is rather for compatibility with similar toolchains which use this statement, but only basic support.
I think #pragma aux is a lot more powerful than similar features in GCC.
Agreed. _asm block is used base on my current situation. I'll try #pragma aux first when I write some from the start.
Line terminator and mutlple statements in __asm block
Main purpose: to use macros. Macros are not expanded in multiple lines, there need to be an terminator of a statement.
BC uses
;
instead of using it as an comment token. GCC uses\n\t
in the assembly string. I was guessing;
would work for open watcom, but it turns out it is a comment token after I checked withwdis