Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 01 Mar 1996 10:28:44 +0530
From:      A JOSEPH KOSHY <koshy@india.hp.com>
To:        Diyamanthi Dahanayake <dahanaya@chaph.usc.edu>
Cc:        hackers@freebsd.org
Subject:   Re: help - assembly 
Message-ID:  <199603010458.AA149776324@fakir.india.hp.com>
In-Reply-To: Your message of "Thu, 29 Feb 1996 11:05:19 PST." <199602291905.LAA21171@nunki.usc.edu> 

next in thread | previous in thread | raw e-mail | index | archive | help

>>>> dd = "Diyamanthi Dahanayake" said:

dd> I need to do some coding in assembly under FreeBSD,
dd> and need some help, specially the syntax. Appreciate

I'll assume that you are familiar with the x86 instruction set :).

For details on the assembler as such you could look at the GAS info files.
(Use the comand `info as').  The man page also gives you some information on 
this.  `AS' allows you to run the assembler source thru the `m4' macro 
processor before actual assembly.  M4 can take effort getting used to, but 
is extremely powerful.  

You may want to look at GCC's "inline" and "asm" directives (as documented
in `info gcc'); these may allow you to get by writing most of your code
in C with machine specific fragments in inline-assembler.  

You can also invoke the assembler thru GCC by creating the file with a 
".S" extension. This allows you to use CPP macros in your assembler file.

If you are familiar with assembly language programming under DOS; then
Unix assembly programming should be straightforward.  The points of
difference that I can remember are :

1.	Instructions have the format 

	OP SOURCE, DESTINATION  # This order is the reverse of the DOS usage.

	"#" starts a comment which goes till the end of line

	Multiple instructions in a line are separated using ";".  E.g:-

	movl -4(%ebp), %esi; rep; movsw

2.	You have to indicate the size of operands as part of the opcode
	mnemonic. 

	For example:

	movl	%eax,	%ebx	# moves 32 bits from eax to ebx
	movw	%ax,	%bx	# moves 16 bits from ax to bx ...

	The suffixes are 'l' for 32 bit operands, 'w' for 16 bit operands,
	'b' for byte operands.  The assembler will cross check that the
	opcode's implied size and the actual sizes of the operands match.
	This catches lots of interesting bugs before they can occur.

3.	Registers are prefixed with a "%".  E.g.:- %eax, %ebx

4.	Indirection is indicated by "()".

	movl	(%eax),	%ebx	# moves 32 bits pointed to by %eax to %ebx

5.	Base + index + offset addressing is coded using the following syntax:

	NN(%r1,%r2,SCALE) 	# where NN is the offset, and the address
				# is NN + %r1 + (%r2 * SCALE). SCALE = 1,2,4,8
	
	(%r1)
	NN(%r1)		
	(%r1,%r2)
	NN(%r1,%r2)		are also valid forms

	The usual x86 addressing restrictions apply of course.

6.	Immediate constants are prefixed with a "$".

	movl	$10, -4(%ebp)	# 

7.	Register usage in functions is as follows : 

	%eax, %ecx, %edx -- no need to save/restore these in your function
	%eax		 -- is used to hold the return value for a function.
	%ebx, %esi, %edi -- should be saved and restored by the called
			    function.
	%esp		-- this is your stack pointer
	%ebp		-- your frame pointer.  Note that optimized code
			   may use %ebp as a general register.  Caveat 
			   programmer.
			
	Don't play with the segment registers unless you really know what
	you are doing :).

8.	On entry to your assembler function setup a stack frame as follows
	(this allows debuggers to make sense of the stack):

	pushl %ebp
	movl %esp, %ebp

	Your first argument is available at 8(%ebp).

A good way to learn how the assembler works is to use `cc -S' to generate 
assembler code and read the resulting ".s" file.

Koshy



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199603010458.AA149776324>