flat assembler
Message board for the users of flat assembler.

flat assembler > High Level Languages > Rules for linking Fasm to g++ on AMD64

Author
Thread Post new topic Reply to topic
fpga



Joined: 22 Sep 2009
Posts: 36
Here's a Fasm program I know works.
Can someone please explain by example what you must do to link this to a g++ program on an AMD64 box so that you can call this "print string" routine from g++.

Any help would be very much appreciated.

Code:
format  ELF executable
entry   start

        SYSCALL_EXIT    equ 1     ; syscall to function exit()
        SYSCALL_WRITE   equ 4     ; syscall to function write()
        STDOUT          equ 1     ; file descriptor of standard output
        ESC             equ 0x1b  ; escape character

start:
; first clear the screen
        mov     eax, SYSCALL_WRITE
        mov     ebx, STDOUT
        mov     ecx, clear_screen
        mov     edx, clear_screen_size
        int     0x80
; move cursor to (x:25, y:12)
        mov     eax, SYSCALL_WRITE
        mov     ebx, STDOUT
        mov     ecx, move_cursor
        mov     edx, move_cursor_size
        int     0x80
; write the message
        mov     eax, SYSCALL_WRITE
        mov     ebx, STDOUT
        mov     ecx, message
        mov     edx, message_size
        int     0x80
; exit from the program
        mov     eax, SYSCALL_EXIT
        xor     ebx, ebx
        int     0x80

clear_screen: db ESC, "[2J"
clear_screen_size = $ - clear_screen
move_cursor:  db ESC, "[12;25H"
move_cursor_size = $ - move_cursor
message:      db ESC, "[31m", ESC, "[5m", ESC, "[4m" ; red, blink on, underline on
              db "Programming linux is easy", 0xa
              db ESC, "[25m", ESC, "[24m" ; blink off, underline off
message_size = $ - message
    
Post 22 Sep 2009, 18:28
View user's profile Send private message Reply with quote
fpga



Joined: 22 Sep 2009
Posts: 36
The asm file containing the function to be called
i.e. print_str_2.fasm
Code:
format ELF64 ;executable             ;change
;format ELF executable

;entry   start 

        SYSCALL_EXIT    equ 1     
        SYSCALL_WRITE   equ 4     
        STDOUT          equ 1     
        ESC             equ 0x1b  

;start:

_print_str:                             ;change
; first clear the screen
        mov     eax, SYSCALL_WRITE
        mov     ebx, STDOUT
        mov     ecx, clear_screen
        mov     edx, clear_screen_size
        int     0x80
; move cursor to (x:25, y:12)
        mov     eax, SYSCALL_WRITE
        mov     ebx, STDOUT
        mov     ecx, move_cursor
        mov     edx, move_cursor_size
        int     0x80
; write the message
        mov     eax, SYSCALL_WRITE
        mov     ebx, STDOUT
        mov     ecx, message
        mov     edx, message_size
        int     0x80
; exit from the program
        mov     eax, SYSCALL_EXIT
        xor     ebx, ebx
        int     0x80
ret                                    ;change ie added

clear_screen: db ESC, "[2J"
clear_screen_size = $ - clear_screen
move_cursor:  db ESC, "[12;25H"
move_cursor_size = $ - move_cursor
message:      db ESC, "[31m", ESC, "[5m", ESC, "[4m" ; red, blink on, underline on
              db "Programming linux is easy", 0xa
              db ESC, "[25m", ESC, "[24m" ; blink off, underline off
message_size = $ - message

    

The c++ file that calls the asm function
i.e. call_asm.cpp
Code:
#include "iostream"
using namespace std;

extern "C" void print_str();

int main(){
   cout << "hi" << endl;
   print_str();
   return 0;
}
    


my compiling shell script
Code:
#!/bin/sh
./fasm print_str_2.fasm print_str_2.o
g++ -c call_asm.cpp
g++ -o blob call_asm.o print_str_2.o
./blob
rm blob
    

and the error message that I get
Code:
flat assembler  version 1.68  (16384 kilobytes memory)
2 passes, 669 bytes.
call_asm.o: In function `main':
call_asm.cppSad.text+0x73): undefined reference to `print_str()'
collect2: ld returned 1 exit status
run.sh: 7: ./blob: not found
rm: cannot remove `blob': No such file or directory
    
Post 23 Sep 2009, 11:42
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 16057
Location: 112 Ocean Avenue, Amityville
What is g++?
Post 23 Sep 2009, 12:24
View user's profile Send private message Visit poster's website Reply with quote
fpga



Joined: 22 Sep 2009
Posts: 36
It's gcc's c++ compiler
Post 23 Sep 2009, 12:51
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 16057
Location: 112 Ocean Avenue, Amityville
I would expect you need to export the function names. Maybe ...
Code:
public _print_str as '_print_str@0'    
Post 23 Sep 2009, 12:56
View user's profile Send private message Visit poster's website Reply with quote
fpga



Joined: 22 Sep 2009
Posts: 36
revolution
Thanks for trying.
I put it as line 2 in print_str_2.fasm and got the same error.
Post 23 Sep 2009, 13:07
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 16057
Location: 112 Ocean Avenue, Amityville
It is probably something to do with name mangling in g++. How does g++ mangle the function names? You need to match the C name mangling in the public directive.
Post 23 Sep 2009, 13:09
View user's profile Send private message Visit poster's website Reply with quote
MazeGen



Joined: 06 Oct 2003
Posts: 953
Location: Czechoslovakia
Compile the call_asm.cpp file and look into the object file what external symbol GCC expects.
Post 23 Sep 2009, 14:47
View user's profile Send private message Visit poster's website Reply with quote
fpga



Joined: 22 Sep 2009
Posts: 36
Sorry to lose the continuity. I had to pop out for a while.

Your comment on mangling seems correct.
Before I went I tried it with gcc and got
Code:
flat assembler  version 1.68  (16384 kilobytes memory)
2 passes, 706 bytes.
call_asm.c:2: error: expected identifier or ‘(’ before string constant
call_asm.o: In function `main':
call_asm.cSad.text+0x14): undefined reference to `print_str'
collect2: ld returned 1 exit status
    


Here's what I did...

Code:
#include <stdio.h>
extern "C" void print_str();
int main (void){
  printf ("Hello, world!\n");
  print_str();
  return 0;
}
    


Code:
format ELF64 ;executable             ;change

public _print_str as '_print_str@0'

;format ELF executable

;entry   start 

        SYSCALL_EXIT    equ 1     
        SYSCALL_WRITE   equ 4     
        STDOUT          equ 1     
        ESC             equ 0x1b  

;start:

_print_str:                             ;change
; first clear the screen
        mov     eax, SYSCALL_WRITE
        mov     ebx, STDOUT
        mov     ecx, clear_screen
        mov     edx, clear_screen_size
        int     0x80
; move cursor to (x:25, y:12)
        mov     eax, SYSCALL_WRITE
        mov     ebx, STDOUT
        mov     ecx, move_cursor
        mov     edx, move_cursor_size
        int     0x80
; write the message
        mov     eax, SYSCALL_WRITE
        mov     ebx, STDOUT
        mov     ecx, message
        mov     edx, message_size
        int     0x80
; exit from the program
        mov     eax, SYSCALL_EXIT
        xor     ebx, ebx
        int     0x80
ret                                    ;change ie added




clear_screen: db ESC, "[2J"
clear_screen_size = $ - clear_screen
move_cursor:  db ESC, "[12;25H"
move_cursor_size = $ - move_cursor
message:      db ESC, "[31m", ESC, "[5m", ESC, "[4m" ; red, blink on, underline on
              db "Programming linux is easy", 0xa
              db ESC, "[25m", ESC, "[24m" ; blink off, underline off
message_size = $ - message


    


Code:
#!/bin/sh
./fasm print_str_2.fasm print_str_2.o
gcc -c call_asm.c
gcc -o blob call_asm.o print_str_2.o
./blob
rm blob
# Exit with successful status
exit 0
    
Post 23 Sep 2009, 14:54
View user's profile Send private message Reply with quote
fpga



Joined: 22 Sep 2009
Posts: 36
objdump -Dslx call_asm.o gives me the following.
I can see print_str in two places but am not sure what else this is telling me about the problem

Code:
call_asm.o:     file format elf64-x86-64
call_asm.o
architecture: i386:x86-64, flags 0x00000011:
HAS_RELOC, HAS_SYMS
start address 0x0000000000000000

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .text         0000001f  0000000000000000  0000000000000000  00000040  2**2
                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
  1 .data         00000000  0000000000000000  0000000000000000  00000060  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  2 .bss          00000000  0000000000000000  0000000000000000  00000060  2**2
                  ALLOC
  3 .rodata       0000000e  0000000000000000  0000000000000000  00000060  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  4 .eh_frame     00000038  0000000000000000  0000000000000000  00000070  2**3
                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
  5 .comment      00000024  0000000000000000  0000000000000000  000000a8  2**0
                  CONTENTS, READONLY
  6 .note.GNU-stack 00000000  0000000000000000  0000000000000000  000000cc  2**0
                  CONTENTS, READONLY
SYMBOL TABLE:
0000000000000000 l    df *ABS*       0000000000000000 call_asm.c
0000000000000000 l    d  .text   0000000000000000 .text
0000000000000000 l    d  .data        0000000000000000 .data
0000000000000000 l    d  .bss 0000000000000000 .bss
0000000000000000 l    d  .rodata       0000000000000000 .rodata
0000000000000000 l    d  .eh_frame  0000000000000000 .eh_frame
0000000000000000 l    d  .note.GNU-stack  0000000000000000 .note.GNU-stack
0000000000000000 l    d  .comment   0000000000000000 .comment
0000000000000000 g     F .text     000000000000001f main
0000000000000000         *UND* 0000000000000000 puts
0000000000000000         *UND* 0000000000000000 print_str     <== here


Contents of section .text:
 0000 554889e5 bf000000 00e80000 0000b800  UH..............
 0010 000000e8 00000000 b8000000 00c9c3    ............... 
Contents of section .rodata:
 0000 48656c6c 6f2c2077 6f726c64 2100      Hello, world!.  
Contents of section .eh_frame:
 0000 14000000 00000000 017a5200 01781001  .........zR..x..
 0010 030c0708 90010000 1c000000 1c000000  ................
 0020 00000000 1f000000 00410e10 8602430d  .........A....C.
 0030 06000000 00000000                    ........        
Contents of section .comment:
 0000 00474343 3a202855 62756e74 7520342e  .GCC: (Ubuntu 4.
 0010 332e332d 35756275 6e747534 2920342e  3.3-5ubuntu4) 4.
 0020 332e3300                             3.3.            

Disassembly of section .text:

0000000000000000 <main>:
main():
   0:    55                      push   %rbp
   1:        48 89 e5                mov    %rsp,%rbp
   4:   bf 00 00 00 00          mov    $0x0,%edi
                    5: R_X86_64_32      .rodata
   9:    e8 00 00 00 00          callq  e <main+0xe>
                   a: R_X86_64_PC32    puts-0x4
   e:   b8 00 00 00 00          mov    $0x0,%eax
  13:   e8 00 00 00 00          callq  18 <main+0x18>
                 14: R_X86_64_PC32   print_str-0x4     <=========here
  18:        b8 00 00 00 00          mov    $0x0,%eax
  1d:   c9                      leaveq 
  1e:    c3                      retq   

Disassembly of section .rodata:

0000000000000000 <.rodata>:
   0:    48                      rex.W
   1:      65                      gs
   2: 6c                      insb   (%dx),%esSad%rdi)
   3:        6c                      insb   (%dx),%esSad%rdi)
   4:        6f                      outsl  %dsSad%rsi),(%dx)
   5:        2c 20                   sub    $0x20,%al
   7:   77 6f                   ja     78 <main+0x78>
   9:        72 6c                   jb     77 <main+0x77>
   b:        64 21 00                and    %eax,%fsSad%rax)

Disassembly of section .eh_frame:

0000000000000000 <.eh_frame>:
   0:     14 00                   adc    $0x0,%al
   2:    00 00                   add    %al,(%rax)
   4:  00 00                   add    %al,(%rax)
   6:  00 00                   add    %al,(%rax)
   8:  01 7a 52                add    %edi,0x52(%rdx)
   b:     00 01                   add    %al,(%rcx)
   d:  78 10                   js     1f <.eh_frame+0x1f>
   f:   01 03                   add    %eax,(%rbx)
  11: 0c 07                   or     $0x7,%al
  13:    08 90 01 00 00 1c       or     %dl,0x1c000001(%rax)
  19:        00 00                   add    %al,(%rax)
  1b:  00 1c 00                add    %bl,(%rax,%rax,1)
  1e:   00 00                   add    %al,(%rax)
  20:  00 00                   add    %al,(%rax)
                   20: R_X86_64_32     .text
  22:      00 00                   add    %al,(%rax)
  24:  1f                      (bad)  
  25:    00 00                   add    %al,(%rax)
  27:  00 00                   add    %al,(%rax)
  29:  41 0e                   rex.B (bad)  
  2b:      10 86 02 43 0d 06       adc    %al,0x60d4302(%rsi)
  31: 00 00                   add    %al,(%rax)
  33:  00 00                   add    %al,(%rax)
  35:  00 00                   add    %al,(%rax)
   ...

Disassembly of section .comment:

0000000000000000 <.comment>:
   0:      00 47 43                add    %al,0x43(%rdi)
   3:      43 3a 20                rex.XB cmp    (%r8),%spl
   6:   28 55 62                sub    %dl,0x62(%rbp)
   9:      75 6e                   jne    79 <main+0x79>
   b:        74 75                   je     82 <main+0x82>
   d:        20 34 2e                and    %dh,(%rsi,%rbp,1)
  10:   33 2e                   xor    (%rsi),%ebp
  12: 33 2d 35 75 62 75       xor    0x75627535(%rip),%ebp        # 7562754d <main+0x7562754d>
  18:     6e                      outsb  %dsSad%rsi),(%dx)
  19:        74 75                   je     90 <main+0x90>
  1b:        34 29                   xor    $0x29,%al
  1d:   20 34 2e                and    %dh,(%rsi,%rbp,1)
  20:   33 2e                   xor    (%rsi),%ebp
  22: 33 00                   xor    (%rax),%eax
    
Post 23 Sep 2009, 15:18
View user's profile Send private message Reply with quote
fpga



Joined: 22 Sep 2009
Posts: 36
Here's the dump for print_str_2.o
Code:

print_str_2.o:     file format elf64-x86-64
print_str_2.o
architecture: i386:x86-64, flags 0x00000011:
HAS_RELOC, HAS_SYMS
start address 0x0000000000000000

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .flat         00000089  0000000000000000  0000000000000000  00000040  2**3
                  CONTENTS, ALLOC, LOAD, RELOC, CODE
SYMBOL TABLE:
0000000000000000 l    d  .flat    0000000000000000 .flat
0000000000000000 g     F .flat        0000000000000000 _print_str@0


Contents of section .flat:
 0000 b8040000 00bb0100 0000b94c 000000ba  ...........L....
 0010 04000000 cd80b804 000000bb 01000000  ................
 0020 b9500000 00ba0800 0000cd80 b8040000  .P..............
 0030 00bb0100 0000b958 000000ba 31000000  .......X....1...
 0040 cd80b801 00000031 dbcd80c3 1b5b324a  .......1.....[2J
 0050 1b5b3132 3b323548 1b5b3331 6d1b5b35  .[12;25H.[31m.[5
 0060 6d1b5b34 6d50726f 6772616d 6d696e67  m.[4mProgramming
 0070 206c696e 75782069 73206561 73790a1b   linux is easy..
 0080 5b32356d 1b5b3234 6d                 [25m.[24m       

Disassembly of section .flat:

0000000000000000 <_print_str@0>:
_print_str@0():
   0:       b8 04 00 00 00          mov    $0x4,%eax
   5:   bb 01 00 00 00          mov    $0x1,%ebx
   a:   b9 4c 00 00 00          mov    $0x4c,%ecx
                   b: R_X86_64_32S     .flat
   f:      ba 04 00 00 00          mov    $0x4,%edx
  14:   cd 80                   int    $0x80
  16:       b8 04 00 00 00          mov    $0x4,%eax
  1b:   bb 01 00 00 00          mov    $0x1,%ebx
  20:   b9 50 00 00 00          mov    $0x50,%ecx
                   21: R_X86_64_32S    .flat
  25:      ba 08 00 00 00          mov    $0x8,%edx
  2a:   cd 80                   int    $0x80
  2c:       b8 04 00 00 00          mov    $0x4,%eax
  31:   bb 01 00 00 00          mov    $0x1,%ebx
  36:   b9 58 00 00 00          mov    $0x58,%ecx
                   37: R_X86_64_32S    .flat
  3b:      ba 31 00 00 00          mov    $0x31,%edx
  40:  cd 80                   int    $0x80
  42:       b8 01 00 00 00          mov    $0x1,%eax
  47:   31 db                   xor    %ebx,%ebx
  49:   cd 80                   int    $0x80
  4b:       c3                      retq   
  4c:    1b 5b 32                sbb    0x32(%rbx),%ebx
  4f:     4a 1b 5b 31             rex.WX sbb    0x31(%rbx),%rbx
  53:      32 3b                   xor    (%rbx),%bh
  55:  32 35 48 1b 5b 33       xor    0x335b1b48(%rip),%dh        # 335b1ba3 <_print_str@0+0x335b1ba3>
  5b:      31 6d 1b                xor    %ebp,0x1b(%rbp)
  5e:     5b                      pop    %rbx
  5f:        35 6d 1b 5b 34          xor    $0x345b1b6d,%eax
  64:    6d                      insl   (%dx),%esSad%rdi)
  65:        50                      push   %rax
  66:        72 6f                   jb     d7 <_print_str@0+0xd7>
  68:        67 72 61                addr32 jb cc <_print_str@0+0xcc>
  6b:     6d                      insl   (%dx),%esSad%rdi)
  6c:        6d                      insl   (%dx),%esSad%rdi)
  6d:        69 6e 67 20 6c 69 6e    imul   $0x6e696c20,0x67(%rsi),%ebp
  74: 75 78                   jne    ee <_print_str@0+0xee>
  76:        20 69 73                and    %ch,0x73(%rcx)
  79:      20 65 61                and    %ah,0x61(%rbp)
  7c:      73 79                   jae    f7 <_print_str@0+0xf7>
  7e:        0a 1b                   or     (%rbx),%bl
  80:  5b                      pop    %rbx
  81:        32 35 6d 1b 5b 32       xor    0x325b1b6d(%rip),%dh        # 325b1bf4 <_print_str@0+0x325b1bf4>
  87:      34 6d                   xor    $0x6d,%al


    
Post 23 Sep 2009, 15:22
View user's profile Send private message Reply with quote
MazeGen



Joined: 06 Oct 2003
Posts: 953
Location: Czechoslovakia
I'm Windows guy so can't try it, however, the puts function is declared as 'puts'. And it expects also 'print_str'. Doesn't this work?
Code:
public _print_str as 'print_str'    

If not, try to ask on a GCC forum how it handles external symbols.
Post 23 Sep 2009, 16:23
View user's profile Send private message Visit poster's website Reply with quote
fpga



Joined: 22 Sep 2009
Posts: 36
No problem. Thx for trying.
I've had a thread on codeguru's non-ms c++ forum since last night.
It's normally very good but on this one I've had 0 responses.

I think I read in the notes that public is for coff output and this is ELF64.
I'll give it a go though.

Despite looking last night and all of today I've failed to find a single working example of g++ calling Fasm. As both are very popular this seems quite strange and suggests that the two don't mix. My best bet therefore seems in-line GAS.

Shame cos I really like the idea of Fasm.
Post 23 Sep 2009, 16:53
View user's profile Send private message Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4634
Location: Argentina
fpga, from your latest fasm code I changed this:
Code:
public _print_str as 'print_str' ; Changed string    


Then, I proceeded this way:

Code:
loco@athlon64:~/Desktop/linktest$ cat call_asm.cpp 

#include "iostream"
using namespace std;

extern "C" void print_str();

int main(){
   cout << "hi" << endl;
   print_str();
   return 0;
}
loco@athlon64:~/Desktop/linktest$ fasm print_str.fasm 
flat assembler  version 1.69.03  (16384 kilobytes memory)
2 passes, 703 bytes.
loco@athlon64:~/Desktop/linktest$ g++ -c call_asm.cpp 
loco@athlon64:~/Desktop/linktest$ g++ -o blob call_asm.o print_str.o
loco@athlon64:~/Desktop/linktest$ uname -a
Linux athlon64 2.6.28-15-generic #49-Ubuntu SMP Tue Aug 18 19:25:34 UTC 2009 x86_64 GNU/Linux    


The results of executing it are attached. (The font changed to red when I executed the code, it was previously black)

[edit]Please not that "public print_str as 'print_str'" would also be valid but I haven't used it because that would required to change more lines (the line with "_print_str:" to "print_str:"). For linking what matters is the name in the quoted string. "public print_str" is equivalent to "public print_str as 'print_str'".


Description:
Filesize: 16.42 KB
Viewed: 8426 Time(s)

linktest.png


Post 23 Sep 2009, 18:33
View user's profile Send private message Reply with quote
fpga



Joined: 22 Sep 2009
Posts: 36
LocoDelAssembly
It took about a minute to get in-line GAS working in g++ and after my difficulty documented above I thought GAS was the way to go.
You've just changed that and I'm very pleased about that.
Thankyou very much for your time and trouble
and to MazeGen and revolution.
Post 23 Sep 2009, 19:06
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2018, Tomasz Grysztar.

Powered by rwasa.