home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.os.msdos.programmer
- Path: sparky!uunet!uunet.ca!geac!zooid!ross
- From: Ross Ridge <ross@zooid.guild.org>
- Subject: Re: djgpp 2.2.2 Q's: mouse/svga/assembler/bios
- Organization: ZOOiD BBS
- Date: Tue, 8 Sep 1992 09:01:32 GMT
- Message-ID: <1992Sep8.090132.6246@zooid.guild.org>
- References: <25586@castle.ed.ac.uk> <18f73jINN2gr@agate.berkeley.edu>
- Lines: 101
-
- benrg@ocf.berkeley.edu (Ben Rudiak-Gould) writes:
- >o Register names like %bl and %cx are not used; instead, the word size
- > is indicated by a letter (`b', `w', or `l') appended to the instruction
- > mnemonic. (This is not done for operations like shrd, where there is
- > no possibility of confusion.)
-
- This isn't true, registers names like %bl and %cx are used. The letter
- suffixes are used instead of the BYTE PTR, WORD PTR, etc... constructs
- of MASM. Suffixes are always required, just not when there is an ambiguity.
-
- >For example, the following function will multiply two fixed-point
- >integers (each with 16 bits of integer and 16 bits of fraction), and
- >return their product as a third:
- >
- >int fixed_mul(int a, int b)
- >{
- > asm("movl 8(%ebp),%eax"); /* get operands from stack into %eax */
- > asm("movl 12(%ebp),%edx"); /* and %edx (%ebp is set up for us) */
- > asm("mull %edx"); /* do the multiplication */
- > asm("shrd $16,%edx,%eax"); /* shift off lower 16 bits from */
- > /* 64-bit result */
- >
- >} /* result is in %eax, which is where djgpp wants it */
- >
- >Note that I deduced the assembly notation from looking at examples, and
- >the inline notation by trial and error. If anybody knows of any official
- >documentation for this (in the full gcc package?) let me know.
-
- The many uses of the "asm" keyword are all described in the in the
- GCC documentation. You'll also need the to look at the machine
- description files for your CPU because it's very machine dependent.
-
- I only have GCC 1.37.1 to work with, so things might be different
- with GCC 2.2.2, but the way you should define the fixed_mul function
- is like this:
-
- int
- fixed_mul(int a, int b) {
- int ret;
-
- asm("mull %2;shrd $16,%%edx,%0"
- /* %0 is replaced with the first operand, %2 is replaced with
- the third operand. A semicolon (;) seperated assembly
- statments */
- : "=a" (ret)
- /* the constraints on the first operand, an output operand. The equals
- sign (=) means that this operand is written to, the letter 'a' means that
- this operand must be the EAX register. In brackets is an lvalue that
- will be loaded with result */
- : "0" (a),
- /* the constraints on the second operand, an input operand. The digit
- '0' means that this operand must be the same the first operand.
- In backets is the value of this operand. */
- "rm" (b)
- /* the constraints on the third operand, an input operand. The letter
- 'r' means that it can be a register, the letter 'm' means that it
- can also be a memory reference. */
- : "dx");
- /* this means that the EDX register is clobberd by this statement */
-
- return ret;
- }
-
- This generates the following code, one instruction shorter with my
- version of GCC:
-
- pushl %ebp
- movl %esp,%ebp
- movl 8(%ebp),%eax
- mull 12(%ebp)
- shrd $16,%edx,%eax
- leave
- ret
-
- or in Intel syntax:
-
- push ebp
- mov ebp,esp
- mov eax,[ebp+0x8]
- mul [ebp+0xc]
- shrd eax,edx,0x10
- leave
- ret
-
- By using operands and constraints we're able to tell GCC about
- all the side effects of the asm statement, and have it load everything
- so we don't have to make any assumption on calling conventions.
- We can easily put it into a macro so it can be used inline:
-
- #define fixed_mul(a, b) ({ int __result; \
- __asm__("mull %2;shrd $16,%%edx,%0": \
- "=a" (_t): "0" ((int)(a)), "rm" ((int)(b)): "dx"); \
- __result })
-
- Ross Ridge
-
- --
- Ross Ridge - The Great HTMU l/ //
- [OO][oo]
- ross@zooid.guild.org /()\/()/
- uunet.ca!zooid!ross db //
-