This discussion was initiated by Privalov at the end of the thread titled 'porting win32 masm code to AIX platform' in Main board.

I personally appreciate Privalov's interst in supporting my primary platform. ;) As a matter of fact, I once post my wish about PIC support with my idea in a thread about ELF format. Anyhow, I'll repeat that in this post.

1. PIC support: why?
Privalov's example at the end of the above thread works because it is an application. That still works if we consider only static libraries. When it comes to dynamic libraries, PIC support becomes an issue. So, if FASM is going to support shared libraries, read on.

Unlike Win32 DLLs, Unix shared libraries really move around in the memory. Therefore, within a dynamic library, one cannot know where is the function he/she wants to call, where is the global variable exported to applications, where are the local variables for the function's own use. ELF documentation explains how to do that. Privalov seems to be familiar with it, but, for others, I'll describe how asm code can be written.

Everything should start with getting the address of the global offset table (GOT).


push ebx
call L0
L0: pop ebx
add ebx,$-L0+_GLOBAL_OFFSET_TABLE_

ebx is conventionally reserved for this purpose. (And, of course, in MASM syntax, L0 and _GLOBLA_OFFSET_TABLE_ should be 'offset' values.)

To access an exported global variable (say, x), one should


mov eax,x@GOT[ebx]

(Forget about the special operator '@'. This should be developed
in FASM syntax. Just think of it as getting address relative to
the beginnign of GOT.)

To access an local variable (say, y) in data section, one should


mov y@GOTOFF[ebx],eax

The difference between local and global variables comes from where those variables are located in the memory. Global variables are allocated in the process address space, and local variables are allocated in the library address space.

To access an external function (say, strlen(3) in libc), one should access it through procedure linkage table (PLT).



lea eax,mystring@GOTOFF[ebx]
push eax
call strlen@PLT


If you are familiar with AT&T syntax, you can always read the relevant system header file for better explanation. For example, it is /usr/include/machine/asm.h in FreeBSD (NetBSD and OpenBSD, too).

Now, GOT, GOTOFF, and PLT are given to programmers. An assembler or a HLL compiler needs to support it internally. Otherwise, it cannot produce shared objects which works correctly. The best case will result in incorrect results, and usually, SIGSEGV. (Yeah, before
I learned how to do it properly, I had generated numerous seg faults.)

2. PIC: how?
I propose to support PIC in the way that 16-bit DOS assembly code uses segment override. For example, obtaining the address of GOT can be written as


push ebx
call L0
L0: pop ebx
add ebx,$-L0+_GLOBAL_OFFSET_TABLE_

Then, calling an external function could be


call PLT:strlen

To access a global variable,


mov eax,GOT(ebx):[glbl_var]

Yes, it is a bit klunky, because GOT has an argument. But, it does not have to be ebx which holds the address of _GLOBAL_OFFSET_TABLE_. Likewise, to access local variables,


mov eax,GOTOFF(ebx):[local1]
mov GOTOFF(ebx):[local2],eax

Or, the following may look better:


mov eax,GOT:[ebx+glbl_var]
lea edx,GOTOFF:[ebx+local1]


I hope others have better ideas about the syntax.

3. Minor issue
One minor issue raised by Privalov: brandelf.
I have not tested the latest FASM under FreeBSD. But, Privalov, did you mean that FASM can be run under FreeBSD (which I know for sure, becasue I did try out FASM 1.4x a while ago)? If you meant that, then it is a non-issue. If you mean that I still need the COFF emulator of linux ld(1) in order to link FASM-created object files, then it is a serious issue. That means, I cannot create a native binary using FASM. That was the other reason (than PIC issue) why I did not continue to use when FASM first supported ELF.
Posted on 2003-01-11 23:25:41 by Starless

If you mean that I still need the COFF emulator of linux ld(1) in order to link FASM-created object files, then it is a serious issue. That means, I cannot create a native binary using FASM. That was the other reason (than PIC issue) why I did not continue to use when FASM first supported ELF.

No, fasm now support ELF objects and ld doesn't complain anything about them. This is the latest version (1.43) which introduced this feature - you can find

Back to the PIC implementation: what about:


mov eax,[ebx+GOT x]
mov [ebx+GOTOFF y],ebx
call PLT strlen

Just analoguous in use to the RVA operator in PE format.
Posted on 2003-01-12 03:40:27 by Tomasz Grysztar


call PLT extrn_fn

looks nice. It reminds me of 'far'/'near' in old days. On the other hand,


mov eax,[ebx+GOT x]

reminds me of horrible NASM syntax. Just in case you don't know, NASM does it like


mov eax,[ebx+x wrt ..got]


I don't know if making it like RVA operator will help making FASM consistent internally. If it does, then you probably want to go for it.
On the other hand, that leaves me wondering how to create a convenience macro (like PIC_GOT() in FreeBSD).
Posted on 2003-01-12 06:24:52 by Starless