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>