This file is vital and MUST be included into program code to do anything else; it provides the framework and macros described here, without it you have to write in usual boring way.
CODESEG, DATASEG, UDATASEG, END, I_STRUC, I_END, B_STRUC macros are here, some other will be added.
Also it contains optimizing macros _mov, _add, _sub, that perform register assignment, addition and subtraction. You can use these macros instead of mov, add, sub instructions -- if you take care of size, this will produce quite good results (do not try to understand how they work :).
Note: when passing negative number in -0x80..0x00 range to _mov, pass it as hex, i.e. 0xffffffff instead of -1, if you want size optimization. This is a "feature" of nasm, not _mov bug.
This file includes two others: includes.inc and syscall.inc, you do need to include them manually.
This file stores generic constant definitions and structures (from libc headers) that are (as a rule) OS independent. If you add some defined constant, please do not forget to mention header file it was taken from.
File holds system call macros, here are general things to know about them:
all parameters are always optional
there can be up to 6 parameters (depends on syscall) on Linux, more on *BSD
registers corresponding to parameters are: ebx (1), ecx (2), edx (3), esi (4), edi (5), ebp (6).
eax register is used as syscall (function) number and is always destroyed; after call it contains return value. Other registers are not touched.
flags can be touched, you should not assume that flags are the same after call
if there are no parameters, macro assumes that all registers (except eax) are already set before syscall
number of used registers is equal to number of passed parameters + 1 (eax)
parameter can be register, memory address, reference, constant or reserved word
reserved words are (currently only one): EMPTY (indicates that register is already set before macro and must be skipped). It is useful when you need to pass only say third parameter and not touch others; e.g. sys_write EMPTY,EMPTY,1 will expand to:
_mov edx,1 __syscall write...
registers are set in this order: ebp, edi, esi, edx, ecx, ebx, eax; therefore it is possible to write sys_write eax, ebx, ecx; it will expand to:
mov edx,ecx mov ecx,ebx mov ebx,eax __syscall write...
generated code can be optimized for size (default) or speed
Warning |
NEVER use __syscall macro in your program directly (of course the same applies to int 0x80 !!). This is a VERY BAD thing to do. This will MAKE YOUR CODE UNPORTABLE! Therefore please use only sys_xxx macros! See also this section . |
If some system call is missing, you can add it to this file; it's simple, just look how others are done there; use sys_syscallname as macro name.
This file applies only to ELF systems. ELF macros are defined here. These macros can be (and are, by default) used to reduce the final size of an executable. Almost all of them (except ELF_AT) are integrated into existing program structure. To enable them you just need to have ELF_MACROS = y line in MCONFIG (enabled by default), this turns on automatic usage of these macros (and you do not have to include elf.inc). And if you will follow simple rules when writing a program, then you do not have to carry out two different definitions for sections and structures; so, you can compile the same source with and without usage of these macros, getting correct code in both cases. Rules are simple: use following section order: CODESEG, DATASEG, UDATASEG, END, and use I_STRUC and I_END to define structures in UDATASEG, or even better, B_STRUC macro, instead of istruc and iend (take any asmutils source as an example), Alternatively, you can use macros from elf.inc directly if you want, but then you can't compile your source using usual nasm/ld procedure. If you want to go this way, take the time and read carefully description by Brian Raiter below and comments in the elf.inc (also do read it if you want to understand how they work). Personally I think that first way is simpler.
elf.inc macros description (by Brian Raiter) -------------------------------------------- ELF executable files can contain a great deal of overhead information. This overhead is used to define things such as the program's memory layout, dynamic libraries which it needs in order to run, and so on. The programs in asmutils, however, require almost none of this overhead (e.g., by making direct system calls). This permits the programs to be much smaller than they would be otherwise. In fact, they require less ELF overhead than Nasm and ld expect of any program. As a result, these tools create executables with unnecessary overhead. Some of this overhead can be removed afterwards using strip and/or sstrip, but not all of it. Therefore, as of version 0.05, the asmutils programs avoid using object files entirely, and instead define the ELF executable file images directly, byte for byte, using Nasm's "bin" output file format and the macros defined in elf.inc. These macros are defined here. BEGIN_ELF END_ELF These are the two main macros in elf.inc. They mark the beginning and the end of the program, and must be used together. All assembler instructions (and pseudo-instructions such as "DB") should appear between these two macros. Within these two macros, the START label should be defined, which will mark the entry point of the program. BEGIN_ELF uses the ORG pseudo-instruction to indicate where the file is to be loaded in memory, and then defines a minimal ELF header and program header table. BEGIN_ELF also defines the label _text to point to the area immediately following its usage (which is typically the beginning of the program). Note that if instructions do appear after the END_ELF macro, they will still be added to the executable file. However, nothing after END_ELF will be loaded into memory when the program is executed. If the program requires no writable data storage outside of the stack, then nothing else from elf.inc will be needed. ELF_DATA This macro is used to reserve writable memory. ELF_DATA should appear after the program proper, and before END_ELF. Between these two macros, the programmer can define "uninitialized" data using the RESB family of pseudo-instructions. Memory defined in the ELF_DATA section will not take up space in the executable file, but will instead be automatically allocated at runtime. The data will be initialized to all zeros. The builtin macro ALIGNB may also be used here. ELF_DATA also defines the label _data to point to the area immediately following its usage. Note: do not use the DB family of pseudo-instructions within the ELF_DATA section; those should appear before ELF_DATA, within the program proper. ELF_BSTRUC strucname [, fieldname ...] This macro declares an instance of a structure (previously defined with the builtin STRUC macro) within an ELF_DATA segment. The structure, in order to work with ELF_BSTRUC, must have been defined using local labels (i.e., prefixed with a dot) for the field names. The first argument to ELF_BSTRUC is the name of the structure to use. The remaining arguments (if any) list the field names to declare. Only those field names specified will be declared as labels within the program. Thus, for example, if the following structure has been defined: struc mytype .long: resd 1 .word: resw 1 .byte: resb 1 .str: resb 32 endstruc then a program that included the following after ELF_DATA: mine: elf_bstruc mytype .long, .word, .str would have 39 bytes added to its memory image, and could use the labels mine.long, mine.word, and mine.str. (mine.byte would not be created.) ELF_ISTRUC strucname ELF_IAT fieldname [, inst ...] ELF_IEND These macros correspond directly to the builtin macros ISTRUCT, AT, and IEND; they differ only in that they declare "uninitialized" memory, and thus can be used within an ELF_DATA section.