22

In this Crash course to Amiga assembly programming, the author loads A6 with a constant, and then regularly jumps to offsets from that constant. He explains: All functions within that library can be accessed by jumping to addresses relative to the base address of the library. So in the example codes on his page first load a CPU register with the base address of exec.library:

move.l  $4,a6

and then we find that jumps to subroutines inside a library go like this:

jsr -132(a6)    ; Forbid

I am used to ELF libraries on Linux. I was expecting to find some way to look up a routine's entry point by the name of the routine, (for example, that's how dlsym etc works. I've never done assembler on Linux though).

Is exec.library always at $4? Are libraries generally loaded at some fixed address, or it this only because exec.library is in a kickstart ROM?

Are the symbol names stored in the libraries anywhere, so that I can look the addresses up?

If I have a different kickstart version, could the entry points in exec.library be different?

2 Answers 2

19

A library in Amiga programming is exactly as you describe - you obtain a pointer to the library base address, and then call a function by loading the library base address into A6, the required parameters into the documented registers, and then doing a jsr to an A6-relative address.

It is unusual to refer to the function addresses by number. The Amiga standard header files will define symbolic names. My memory is a bit hazy, but I think the code you quoted would more commonly be written as:

include "exec/exec.i"

...

jsr _LVOForbid(a6)

(_LVO is a standard prefix for library function symbols; LVO stands for library vector offset.)

Yes, a pointer to exec.library is always at $4, and this is (in theory, but not in practice) the only fixed address you should ever use in AmigaOS. To obtain the base address for any other library, you have to ask exec.library. It has a function OpenLibrary which takes a library name and a minimum version and will return to you the base address of the requested library.

If you follow the pattern of getting the pointer to exec.library from $4 and then calling OpenLibrary for every other library, then you will be compatible with different Kickstart versions. Well-written libraries will be backward-compatible, that is, the old functions will continue to be work as is on newer Kickstarts. This is why OpenLibrary takes a library version number: you must ask for the smallest version number that contains all the functions you need. If the library is not present with the requested version number or newer, OpenLibrary will return NULL (which is a condition you should test for!)

The libraries themselves don't contain the symbol names of the functions - they are fully linked and resolved so there's no symbol table. So you will need the header files to use the symbolic names, at least when you are programming in assembly. When programming in C, you would normally link with a stub linker library that defines functions with the same names, and performs the library call on your behalf.

It is mandatory to put the library base pointer into A6 (necessary so that the library can find its own data; there are very few exceptions to this rule) but once you have completed the library call, you can clear A6 and use it for other purposes. You can have multiple libraries open at once; typically you would store their pointer in a variable, and load the variable into A6 just before making a library call.

http://amigadev.elowar.com/ contains lots of information about developing for AmigaOS, including descriptions of all the standard libraries.

5
  • I agree. library vector offset is always at $4. Where it points to can vary though. (I vaguely remember my derringer 030 board changing that and moving libraries into its faster memory). Which just means that the OP really needs to check/use $4 and not assume that it always has the same value.
    – Hennes
    Jan 25, 2017 at 14:38
  • @Wilson, that's correct. The actual .library itself does not contain the names. This is rarely an issue when writing code as the header files are usually bundled with the development tools, but does mean that you can't use the equivalent of nm to poke around a library to see if there's anything interesting inside it :-) Jan 25, 2017 at 16:10
  • @Wilson you only need to load A6 with the library base address when to want to call that library. When you want to call a different library, simply reload A6 with the required library base address. And the rest of the time you can use A6 however you please. Jan 25, 2017 at 20:50
  • 3
    @Wilson: the code inside the library may access the shared data of the library via the a6 register, so it’s mandatory to have it there when calling a library function, unless specified otherwise. There were only a few, performance critical libraries stating that having the library address in register a6 is not required for particular functions. In all other cases, it’s required.
    – Holger
    Jan 26, 2017 at 15:25
  • There are FD files which contain the names of the standard Amiga library functions at amigadev.elowar.com/read/ADCD_2.1/… and the jump offsets can be computed from these. These weren't distributed along with the libraries themselves but were available separately. Feb 7, 2017 at 7:47
9

@RichardDowner has already answered it, but who don't want pictures? 🤖 These are from the Amiga ROM Kernel Reference Manual: Libraries, 3rd edition, @1992 by Commodore Electronics, Ltd.

Figure 1.1: Amiga Library Structure and Jump Table

What Every Amiga Programmer Should Know: The functions in the Amiga OS are accessed through shared run-time libraries. Libraries must be opened before their functions may be used. The systems master library, Exec, is always open. The exec function OpenLibrary() is used to open all other libraries.

Figure 1.2: Exec and the Organization of the Amiga OS

What Every Amiga Programmer Should Know: The Amiga has a dynamic memory map. There are no fixed locations for operating system variables and routines. Do not call ROM routines or access system data structures directly. Instead use the indirect access methods provided by the system.

If I have a different kickstart version,
could the entry points in exec.library be different?

With the one absolute entry point at Sysbase, no, it won't be. Everything else is relative and should be accessed via library calls.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .