Date : Wed, 27 Jul 1994 18:20:24 EST
From : Stephen Quan <quan@...>
Subject: Re: JB's macros!
Stephen Quan (that's me!) writes :
>And I was just wondering, (actually I had thought of this before),
>with C, you could use imbedded assebly. Keep the macro as it is
>above, but you could have
>
> #ifdef _386_
> #define inc_PC(len) \
> _asm add si,len
> #endif
>
> #ifdef _SPARC_
> #define inc_PC(len) \
> _asm add %o1,len,%o1
> #endif
James B writes :
> Is there a document available (preferably online) that describes how to use
> asm? It always struck me as odd that you can do:
>
> _asm add %o1,len,%o1.
This is SPARC assembly, I was demonstrating the point that it is possible
to write portable assembly code. The above has no meaning for a PC.
I think it is add register %o1 with len and store the result back into
%o1. In general, I guess, you can have
add a,b,c
Which probably means: c = a + b. I haven't played around with Sun SPARC
assembly all that much, to be honest.
> This uses the first of the output registers (%o1) for the addition. How do we
> know which register to use!? Isn't that the compilers task and not ours? Is
> there a standard way of requesting PC to be register %o1? (There is in gcc -
> just).
I am afraid, it means taking over control and leaving practically nothing
in C. This is Chris Rae's method of using the Pascal Compiler. Under,
Turbo Pascal, I suspect he did something like
Program MyEmulator;
Begin
ASM
/* all ASM stuff goes in here. */
END;
End.
The direct parallel in C would be
main()
{
asm {
/* all ASM stuff goes in here. */
}
}
For instance,
main()
{
_asm {
@... mov es,0xe000
mov si,0x0000
mov ah,00h
@... mov al,[es:si]
inc si
}
}
So I have decided that :
SI = beeb PC
AX = opcode (actually AH=0, AL=opcode)
BH = beeb A
BL = beeb X
CH = beeb Y
CL = beeb S
DX = unused.
But in doing so, I have restricted myself to using assembly.
I have seen in some DOS compilers, such as Microsoft C and Borland C,
that you can access these variables directly in C.
#include <dos.h>
main()
{
_AX = 0;
}
Which would be exactly the same as
main()
{
mov ax,0;
}
Also, I can do wild stuff such as (this is taken from my mouse library) :
initmouse()
{
_asm mov ax,0000h
_asm int 33h
}
showmouse()
{
_asm mov ax,0001h
_asm int 33h
}
hidemouse()
{
_asm mov ax,0002h
_asm int 33h
}
getmouse(int *b,int *x,int *y)
{
unsigned local_b,local_x,local_y
_asm mov ax,0003h
_asm int 33h
_asm mov local_b,bx
_asm mov local_x,cx
_asm mov local_y,dx
}
In particular the last example shows how you would mix registers with
C variables. So either you can treat the registers as temporary values
(as in getmouse) which must be copied to real C registers. Or you could
opt for coding most of your stuff in ASM, but make use of the C macros
to make things look neat.
> >#define Jmp(label) _asm jmp @label
> >#define Label(label) _asm @label:
> >#define Equw(label) _asm @label
>
> Is this @label notation part of the _asm semantics? Or is it architecture (and
> maybe even 'as' (the UNIX assembler)) dependant?
> If I could use assembly in the macros of my code it would enable, amongst
> other things, the use of using the 386 status register as discussed in earlier
> threads.
Most certainly you can! Actually I haven't thought about it, but it
is really easy to do. You do need a reference to 386 assembly, or
go compiling with the C compiler's -S option to get example code
fragments, but it is possible.
For instance
main()
{
unsigned char Y;
/* DEY */
_asm pop ah
_asm dec Y
_asm lahf
_asm push ah
}
I don't see any reason why this won't work.
--
Stephen Quan (quan@... ), SysAdmin, Analyst/Programmer.
Centre for Spatial Information Studies, University of Tasmania, Hobart.
GPO BOX 252C, Australia, 7001. Local Tel: (002) 202898 Fax: (002) 240282
International Callers use +6102 instead of (002).