/usr/share/doc/nasm/html/nasmdoc9.html is in nasm 2.11.05-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 | <html><head><title>NASM Manual</title></head>
<body><h1 align=center>The Netwide Assembler: NASM</h1>
<p align=center><a href="nasmdo10.html">Next Chapter</a> |
<a href="nasmdoc8.html">Previous Chapter</a> |
<a href="nasmdoc0.html">Contents</a> |
<a href="nasmdoci.html">Index</a>
<h2><a name="chapter-9">Chapter 9: Writing 32-bit Code (Unix, Win32, DJGPP)</a></h2>
<p>This chapter attempts to cover some of the common issues involved when
writing 32-bit code, to run under Win32 or Unix, or to be linked with C
code generated by a Unix-style C compiler such as DJGPP. It covers how to
write assembly code to interface with 32-bit C routines, and how to write
position-independent code for shared libraries.
<p>Almost all 32-bit code, and in particular all code running under
<code><nobr>Win32</nobr></code>, <code><nobr>DJGPP</nobr></code> or any of
the PC Unix variants, runs in <em>flat</em> memory model. This means that
the segment registers and paging have already been set up to give you the
same 32-bit 4Gb address space no matter what segment you work relative to,
and that you should ignore all segment registers completely. When writing
flat-model application code, you never need to use a segment override or
modify any segment register, and the code-section addresses you pass to
<code><nobr>CALL</nobr></code> and <code><nobr>JMP</nobr></code> live in
the same address space as the data-section addresses you access your
variables by and the stack-section addresses you access local variables and
procedure parameters by. Every address is 32 bits long and contains only an
offset part.
<h3><a name="section-9.1">9.1 Interfacing to 32-bit C Programs</a></h3>
<p>A lot of the discussion in <a href="nasmdoc8.html#section-8.4">section
8.4</a>, about interfacing to 16-bit C programs, still applies when working
in 32 bits. The absence of memory models or segmentation worries simplifies
things a lot.
<h4><a name="section-9.1.1">9.1.1 External Symbol Names</a></h4>
<p>Most 32-bit C compilers share the convention used by 16-bit compilers,
that the names of all global symbols (functions or data) they define are
formed by prefixing an underscore to the name as it appears in the C
program. However, not all of them do: the <code><nobr>ELF</nobr></code>
specification states that C symbols do <em>not</em> have a leading
underscore on their assembly-language names.
<p>The older Linux <code><nobr>a.out</nobr></code> C compiler, all
<code><nobr>Win32</nobr></code> compilers, <code><nobr>DJGPP</nobr></code>,
and <code><nobr>NetBSD</nobr></code> and <code><nobr>FreeBSD</nobr></code>,
all use the leading underscore; for these compilers, the macros
<code><nobr>cextern</nobr></code> and <code><nobr>cglobal</nobr></code>, as
given in <a href="nasmdoc8.html#section-8.4.1">section 8.4.1</a>, will
still work. For <code><nobr>ELF</nobr></code>, though, the leading
underscore should not be used.
<p>See also <a href="nasmdoc2.html#section-2.1.27">section 2.1.27</a>.
<h4><a name="section-9.1.2">9.1.2 Function Definitions and Function Calls</a></h4>
<p>The C calling convention in 32-bit programs is as follows. In the
following description, the words <em>caller</em> and <em>callee</em> are
used to denote the function doing the calling and the function which gets
called.
<ul>
<li>The caller pushes the function's parameters on the stack, one after
another, in reverse order (right to left, so that the first argument
specified to the function is pushed last).
<li>The caller then executes a near <code><nobr>CALL</nobr></code>
instruction to pass control to the callee.
<li>The callee receives control, and typically (although this is not
actually necessary, in functions which do not need to access their
parameters) starts by saving the value of <code><nobr>ESP</nobr></code> in
<code><nobr>EBP</nobr></code> so as to be able to use
<code><nobr>EBP</nobr></code> as a base pointer to find its parameters on
the stack. However, the caller was probably doing this too, so part of the
calling convention states that <code><nobr>EBP</nobr></code> must be
preserved by any C function. Hence the callee, if it is going to set up
<code><nobr>EBP</nobr></code> as a frame pointer, must push the previous
value first.
<li>The callee may then access its parameters relative to
<code><nobr>EBP</nobr></code>. The doubleword at
<code><nobr>[EBP]</nobr></code> holds the previous value of
<code><nobr>EBP</nobr></code> as it was pushed; the next doubleword, at
<code><nobr>[EBP+4]</nobr></code>, holds the return address, pushed
implicitly by <code><nobr>CALL</nobr></code>. The parameters start after
that, at <code><nobr>[EBP+8]</nobr></code>. The leftmost parameter of the
function, since it was pushed last, is accessible at this offset from
<code><nobr>EBP</nobr></code>; the others follow, at successively greater
offsets. Thus, in a function such as <code><nobr>printf</nobr></code> which
takes a variable number of parameters, the pushing of the parameters in
reverse order means that the function knows where to find its first
parameter, which tells it the number and type of the remaining ones.
<li>The callee may also wish to decrease <code><nobr>ESP</nobr></code>
further, so as to allocate space on the stack for local variables, which
will then be accessible at negative offsets from
<code><nobr>EBP</nobr></code>.
<li>The callee, if it wishes to return a value to the caller, should leave
the value in <code><nobr>AL</nobr></code>, <code><nobr>AX</nobr></code> or
<code><nobr>EAX</nobr></code> depending on the size of the value.
Floating-point results are typically returned in
<code><nobr>ST0</nobr></code>.
<li>Once the callee has finished processing, it restores
<code><nobr>ESP</nobr></code> from <code><nobr>EBP</nobr></code> if it had
allocated local stack space, then pops the previous value of
<code><nobr>EBP</nobr></code>, and returns via
<code><nobr>RET</nobr></code> (equivalently,
<code><nobr>RETN</nobr></code>).
<li>When the caller regains control from the callee, the function
parameters are still on the stack, so it typically adds an immediate
constant to <code><nobr>ESP</nobr></code> to remove them (instead of
executing a number of slow <code><nobr>POP</nobr></code> instructions).
Thus, if a function is accidentally called with the wrong number of
parameters due to a prototype mismatch, the stack will still be returned to
a sensible state since the caller, which <em>knows</em> how many parameters
it pushed, does the removing.
</ul>
<p>There is an alternative calling convention used by Win32 programs for
Windows API calls, and also for functions called <em>by</em> the Windows
API such as window procedures: they follow what Microsoft calls the
<code><nobr>__stdcall</nobr></code> convention. This is slightly closer to
the Pascal convention, in that the callee clears the stack by passing a
parameter to the <code><nobr>RET</nobr></code> instruction. However, the
parameters are still pushed in right-to-left order.
<p>Thus, you would define a function in C style in the following way:
<p><pre>
global _myfunc
_myfunc:
push ebp
mov ebp,esp
sub esp,0x40 ; 64 bytes of local stack space
mov ebx,[ebp+8] ; first parameter to function
; some more code
leave ; mov esp,ebp / pop ebp
ret
</pre>
<p>At the other end of the process, to call a C function from your assembly
code, you would do something like this:
<p><pre>
extern _printf
; and then, further down...
push dword [myint] ; one of my integer variables
push dword mystring ; pointer into my data segment
call _printf
add esp,byte 8 ; `byte' saves space
; then those data items...
segment _DATA
myint dd 1234
mystring db 'This number -> %d <- should be 1234',10,0
</pre>
<p>This piece of code is the assembly equivalent of the C code
<p><pre>
int myint = 1234;
printf("This number -> %d <- should be 1234\n", myint);
</pre>
<h4><a name="section-9.1.3">9.1.3 Accessing Data Items</a></h4>
<p>To get at the contents of C variables, or to declare variables which C
can access, you need only declare the names as
<code><nobr>GLOBAL</nobr></code> or <code><nobr>EXTERN</nobr></code>.
(Again, the names require leading underscores, as stated in
<a href="#section-9.1.1">section 9.1.1</a>.) Thus, a C variable declared as
<code><nobr>int i</nobr></code> can be accessed from assembler as
<p><pre>
extern _i
mov eax,[_i]
</pre>
<p>And to declare your own integer variable which C programs can access as
<code><nobr>extern int j</nobr></code>, you do this (making sure you are
assembling in the <code><nobr>_DATA</nobr></code> segment, if necessary):
<p><pre>
global _j
_j dd 0
</pre>
<p>To access a C array, you need to know the size of the components of the
array. For example, <code><nobr>int</nobr></code> variables are four bytes
long, so if a C program declares an array as
<code><nobr>int a[10]</nobr></code>, you can access
<code><nobr>a[3]</nobr></code> by coding
<code><nobr>mov ax,[_a+12]</nobr></code>. (The byte offset 12 is obtained
by multiplying the desired array index, 3, by the size of the array
element, 4.) The sizes of the C base types in 32-bit compilers are: 1 for
<code><nobr>char</nobr></code>, 2 for <code><nobr>short</nobr></code>, 4
for <code><nobr>int</nobr></code>, <code><nobr>long</nobr></code> and
<code><nobr>float</nobr></code>, and 8 for
<code><nobr>double</nobr></code>. Pointers, being 32-bit addresses, are
also 4 bytes long.
<p>To access a C data structure, you need to know the offset from the base
of the structure to the field you are interested in. You can either do this
by converting the C structure definition into a NASM structure definition
(using <code><nobr>STRUC</nobr></code>), or by calculating the one offset
and using just that.
<p>To do either of these, you should read your C compiler's manual to find
out how it organizes data structures. NASM gives no special alignment to
structure members in its own <code><nobr>STRUC</nobr></code> macro, so you
have to specify alignment yourself if the C compiler generates it.
Typically, you might find that a structure like
<p><pre>
struct {
char c;
int i;
} foo;
</pre>
<p>might be eight bytes long rather than five, since the
<code><nobr>int</nobr></code> field would be aligned to a four-byte
boundary. However, this sort of feature is sometimes a configurable option
in the C compiler, either using command-line options or
<code><nobr>#pragma</nobr></code> lines, so you have to find out how your
own compiler does it.
<h4><a name="section-9.1.4">9.1.4 <code><nobr>c32.mac</nobr></code>: Helper Macros for the 32-bit C Interface</a></h4>
<p>Included in the NASM archives, in the <code><nobr>misc</nobr></code>
directory, is a file <code><nobr>c32.mac</nobr></code> of macros. It
defines three macros: <code><nobr>proc</nobr></code>,
<code><nobr>arg</nobr></code> and <code><nobr>endproc</nobr></code>. These
are intended to be used for C-style procedure definitions, and they
automate a lot of the work involved in keeping track of the calling
convention.
<p>An example of an assembly function using the macro set is given here:
<p><pre>
proc _proc32
%$i arg
%$j arg
mov eax,[ebp + %$i]
mov ebx,[ebp + %$j]
add eax,[ebx]
endproc
</pre>
<p>This defines <code><nobr>_proc32</nobr></code> to be a procedure taking
two arguments, the first (<code><nobr>i</nobr></code>) an integer and the
second (<code><nobr>j</nobr></code>) a pointer to an integer. It returns
<code><nobr>i + *j</nobr></code>.
<p>Note that the <code><nobr>arg</nobr></code> macro has an
<code><nobr>EQU</nobr></code> as the first line of its expansion, and since
the label before the macro call gets prepended to the first line of the
expanded macro, the <code><nobr>EQU</nobr></code> works, defining
<code><nobr>%$i</nobr></code> to be an offset from
<code><nobr>BP</nobr></code>. A context-local variable is used, local to
the context pushed by the <code><nobr>proc</nobr></code> macro and popped
by the <code><nobr>endproc</nobr></code> macro, so that the same argument
name can be used in later procedures. Of course, you don't <em>have</em> to
do that.
<p><code><nobr>arg</nobr></code> can take an optional parameter, giving the
size of the argument. If no size is given, 4 is assumed, since it is likely
that many function parameters will be of type <code><nobr>int</nobr></code>
or pointers.
<h3><a name="section-9.2">9.2 Writing NetBSD/FreeBSD/OpenBSD and Linux/ELF Shared Libraries</a></h3>
<p><code><nobr>ELF</nobr></code> replaced the older
<code><nobr>a.out</nobr></code> object file format under Linux because it
contains support for position-independent code (PIC), which makes writing
shared libraries much easier. NASM supports the
<code><nobr>ELF</nobr></code> position-independent code features, so you
can write Linux <code><nobr>ELF</nobr></code> shared libraries in NASM.
<p>NetBSD, and its close cousins FreeBSD and OpenBSD, take a different
approach by hacking PIC support into the <code><nobr>a.out</nobr></code>
format. NASM supports this as the <code><nobr>aoutb</nobr></code> output
format, so you can write BSD shared libraries in NASM too.
<p>The operating system loads a PIC shared library by memory-mapping the
library file at an arbitrarily chosen point in the address space of the
running process. The contents of the library's code section must therefore
not depend on where it is loaded in memory.
<p>Therefore, you cannot get at your variables by writing code like this:
<p><pre>
mov eax,[myvar] ; WRONG
</pre>
<p>Instead, the linker provides an area of memory called the <em>global
offset table</em>, or GOT; the GOT is situated at a constant distance from
your library's code, so if you can find out where your library is loaded
(which is typically done using a <code><nobr>CALL</nobr></code> and
<code><nobr>POP</nobr></code> combination), you can obtain the address of
the GOT, and you can then load the addresses of your variables out of
linker-generated entries in the GOT.
<p>The <em>data</em> section of a PIC shared library does not have these
restrictions: since the data section is writable, it has to be copied into
memory anyway rather than just paged in from the library file, so as long
as it's being copied it can be relocated too. So you can put ordinary types
of relocation in the data section without too much worry (but see
<a href="#section-9.2.4">section 9.2.4</a> for a caveat).
<h4><a name="section-9.2.1">9.2.1 Obtaining the Address of the GOT</a></h4>
<p>Each code module in your shared library should define the GOT as an
external symbol:
<p><pre>
extern _GLOBAL_OFFSET_TABLE_ ; in ELF
extern __GLOBAL_OFFSET_TABLE_ ; in BSD a.out
</pre>
<p>At the beginning of any function in your shared library which plans to
access your data or BSS sections, you must first calculate the address of
the GOT. This is typically done by writing the function in this form:
<p><pre>
func: push ebp
mov ebp,esp
push ebx
call .get_GOT
.get_GOT:
pop ebx
add ebx,_GLOBAL_OFFSET_TABLE_+$$-.get_GOT wrt ..gotpc
; the function body comes here
mov ebx,[ebp-4]
mov esp,ebp
pop ebp
ret
</pre>
<p>(For BSD, again, the symbol
<code><nobr>_GLOBAL_OFFSET_TABLE</nobr></code> requires a second leading
underscore.)
<p>The first two lines of this function are simply the standard C prologue
to set up a stack frame, and the last three lines are standard C function
epilogue. The third line, and the fourth to last line, save and restore the
<code><nobr>EBX</nobr></code> register, because PIC shared libraries use
this register to store the address of the GOT.
<p>The interesting bit is the <code><nobr>CALL</nobr></code> instruction
and the following two lines. The <code><nobr>CALL</nobr></code> and
<code><nobr>POP</nobr></code> combination obtains the address of the label
<code><nobr>.get_GOT</nobr></code>, without having to know in advance where
the program was loaded (since the <code><nobr>CALL</nobr></code>
instruction is encoded relative to the current position). The
<code><nobr>ADD</nobr></code> instruction makes use of one of the special
PIC relocation types: GOTPC relocation. With the
<code><nobr>WRT ..gotpc</nobr></code> qualifier specified, the symbol
referenced (here <code><nobr>_GLOBAL_OFFSET_TABLE_</nobr></code>, the
special symbol assigned to the GOT) is given as an offset from the
beginning of the section. (Actually, <code><nobr>ELF</nobr></code> encodes
it as the offset from the operand field of the
<code><nobr>ADD</nobr></code> instruction, but NASM simplifies this
deliberately, so you do things the same way for both
<code><nobr>ELF</nobr></code> and <code><nobr>BSD</nobr></code>.) So the
instruction then <em>adds</em> the beginning of the section, to get the
real address of the GOT, and subtracts the value of
<code><nobr>.get_GOT</nobr></code> which it knows is in
<code><nobr>EBX</nobr></code>. Therefore, by the time that instruction has
finished, <code><nobr>EBX</nobr></code> contains the address of the GOT.
<p>If you didn't follow that, don't worry: it's never necessary to obtain
the address of the GOT by any other means, so you can put those three
instructions into a macro and safely ignore them:
<p><pre>
%macro get_GOT 0
call %%getgot
%%getgot:
pop ebx
add ebx,_GLOBAL_OFFSET_TABLE_+$$-%%getgot wrt ..gotpc
%endmacro
</pre>
<h4><a name="section-9.2.2">9.2.2 Finding Your Local Data Items</a></h4>
<p>Having got the GOT, you can then use it to obtain the addresses of your
data items. Most variables will reside in the sections you have declared;
they can be accessed using the <code><nobr>..gotoff</nobr></code> special
<code><nobr>WRT</nobr></code> type. The way this works is like this:
<p><pre>
lea eax,[ebx+myvar wrt ..gotoff]
</pre>
<p>The expression <code><nobr>myvar wrt ..gotoff</nobr></code> is
calculated, when the shared library is linked, to be the offset to the
local variable <code><nobr>myvar</nobr></code> from the beginning of the
GOT. Therefore, adding it to <code><nobr>EBX</nobr></code> as above will
place the real address of <code><nobr>myvar</nobr></code> in
<code><nobr>EAX</nobr></code>.
<p>If you declare variables as <code><nobr>GLOBAL</nobr></code> without
specifying a size for them, they are shared between code modules in the
library, but do not get exported from the library to the program that
loaded it. They will still be in your ordinary data and BSS sections, so
you can access them in the same way as local variables, using the above
<code><nobr>..gotoff</nobr></code> mechanism.
<p>Note that due to a peculiarity of the way BSD
<code><nobr>a.out</nobr></code> format handles this relocation type, there
must be at least one non-local symbol in the same section as the address
you're trying to access.
<h4><a name="section-9.2.3">9.2.3 Finding External and Common Data Items</a></h4>
<p>If your library needs to get at an external variable (external to the
<em>library</em>, not just to one of the modules within it), you must use
the <code><nobr>..got</nobr></code> type to get at it. The
<code><nobr>..got</nobr></code> type, instead of giving you the offset from
the GOT base to the variable, gives you the offset from the GOT base to a
GOT <em>entry</em> containing the address of the variable. The linker will
set up this GOT entry when it builds the library, and the dynamic linker
will place the correct address in it at load time. So to obtain the address
of an external variable <code><nobr>extvar</nobr></code> in
<code><nobr>EAX</nobr></code>, you would code
<p><pre>
mov eax,[ebx+extvar wrt ..got]
</pre>
<p>This loads the address of <code><nobr>extvar</nobr></code> out of an
entry in the GOT. The linker, when it builds the shared library, collects
together every relocation of type <code><nobr>..got</nobr></code>, and
builds the GOT so as to ensure it has every necessary entry present.
<p>Common variables must also be accessed in this way.
<h4><a name="section-9.2.4">9.2.4 Exporting Symbols to the Library User</a></h4>
<p>If you want to export symbols to the user of the library, you have to
declare whether they are functions or data, and if they are data, you have
to give the size of the data item. This is because the dynamic linker has
to build procedure linkage table entries for any exported functions, and
also moves exported data items away from the library's data section in
which they were declared.
<p>So to export a function to users of the library, you must use
<p><pre>
global func:function ; declare it as a function
func: push ebp
; etc.
</pre>
<p>And to export a data item such as an array, you would have to code
<p><pre>
global array:data array.end-array ; give the size too
array: resd 128
.end:
</pre>
<p>Be careful: If you export a variable to the library user, by declaring
it as <code><nobr>GLOBAL</nobr></code> and supplying a size, the variable
will end up living in the data section of the main program, rather than in
your library's data section, where you declared it. So you will have to
access your own global variable with the <code><nobr>..got</nobr></code>
mechanism rather than <code><nobr>..gotoff</nobr></code>, as if it were
external (which, effectively, it has become).
<p>Equally, if you need to store the address of an exported global in one
of your data sections, you can't do it by means of the standard sort of
code:
<p><pre>
dataptr: dd global_data_item ; WRONG
</pre>
<p>NASM will interpret this code as an ordinary relocation, in which
<code><nobr>global_data_item</nobr></code> is merely an offset from the
beginning of the <code><nobr>.data</nobr></code> section (or whatever); so
this reference will end up pointing at your data section instead of at the
exported global which resides elsewhere.
<p>Instead of the above code, then, you must write
<p><pre>
dataptr: dd global_data_item wrt ..sym
</pre>
<p>which makes use of the special <code><nobr>WRT</nobr></code> type
<code><nobr>..sym</nobr></code> to instruct NASM to search the symbol table
for a particular symbol at that address, rather than just relocating by
section base.
<p>Either method will work for functions: referring to one of your
functions by means of
<p><pre>
funcptr: dd my_function
</pre>
<p>will give the user the address of the code you wrote, whereas
<p><pre>
funcptr: dd my_function wrt ..sym
</pre>
<p>will give the address of the procedure linkage table for the function,
which is where the calling program will <em>believe</em> the function
lives. Either address is a valid way to call the function.
<h4><a name="section-9.2.5">9.2.5 Calling Procedures Outside the Library</a></h4>
<p>Calling procedures outside your shared library has to be done by means
of a <em>procedure linkage table</em>, or PLT. The PLT is placed at a known
offset from where the library is loaded, so the library code can make calls
to the PLT in a position-independent way. Within the PLT there is code to
jump to offsets contained in the GOT, so function calls to other shared
libraries or to routines in the main program can be transparently passed
off to their real destinations.
<p>To call an external routine, you must use another special PIC relocation
type, <code><nobr>WRT ..plt</nobr></code>. This is much easier than the
GOT-based ones: you simply replace calls such as
<code><nobr>CALL printf</nobr></code> with the PLT-relative version
<code><nobr>CALL printf WRT ..plt</nobr></code>.
<h4><a name="section-9.2.6">9.2.6 Generating the Library File</a></h4>
<p>Having written some code modules and assembled them to
<code><nobr>.o</nobr></code> files, you then generate your shared library
with a command such as
<p><pre>
ld -shared -o library.so module1.o module2.o # for ELF
ld -Bshareable -o library.so module1.o module2.o # for BSD
</pre>
<p>For ELF, if your shared library is going to reside in system directories
such as <code><nobr>/usr/lib</nobr></code> or
<code><nobr>/lib</nobr></code>, it is usually worth using the
<code><nobr>-soname</nobr></code> flag to the linker, to store the final
library file name, with a version number, into the library:
<p><pre>
ld -shared -soname library.so.1 -o library.so.1.2 *.o
</pre>
<p>You would then copy <code><nobr>library.so.1.2</nobr></code> into the
library directory, and create <code><nobr>library.so.1</nobr></code> as a
symbolic link to it.
<p align=center><a href="nasmdo10.html">Next Chapter</a> |
<a href="nasmdoc8.html">Previous Chapter</a> |
<a href="nasmdoc0.html">Contents</a> |
<a href="nasmdoci.html">Index</a>
</body></html>
|