Search code examples
cassemblygcclinker-errorsdjgpp

Linking error [undefined reference to `asm_main()'] in linking Assembly to C


My exact issue is that am trying to get the linked final exe from 3 files namely:

  • The main c loader
  • The main asm file
  • The accessory asm file that holds the functions.

I manage to convert them all successfully to their subsequent object files, but when linking, I get the undefined reference to 'asm_main()' error.

My C file is simple and looks like this:

#include "cdecl.h"

int PRE_CDECL asm_main( void ) POST_CDECL;
int main()
{
    int ret_status;
    ret_status = asm_main();
    return ret_status ;
}

It points to the main asm file that has the following section:

%include "asm_io.inc"
;
; initialized data is put in the .data segment
;
segment .data
;
; These labels refer to strings used for output
;
prompt1 db    "Enter a number: ", 0       ; don't forget nul terminator
prompt2 db    "Enter another number: ", 0
outmsg1 db    "You entered ", 0
outmsg2 db    " and ", 0
outmsg3 db    ", the sum of these is ", 0


;
; uninitialized data is put in the .bss segment
;
segment .bss
;
; These labels refer to double words used to store the inputs
;
input1  resd 1
input2  resd 1

 

;
; code is put in the .text segment
;
segment .text
        global  _asm_main
_asm_main:
        enter   0,0               ; setup routine
        pusha

        mov     eax, prompt1      ; print out prompt
        call    print_string

        call    read_int          ; read integer
        mov     [input1], eax     ; store into input1

        mov     eax, prompt2      ; print out prompt
        call    print_string

        call    read_int          ; read integer
        mov     [input2], eax     ; store into input2

        mov     eax, [input1]     ; eax = dword at input1
        add     eax, [input2]     ; eax += dword at input2
        mov     ebx, eax          ; ebx = eax
        dump_regs 1               ; dump out register values
        dump_mem 2, outmsg1, 1    ; dump out memory
;
; next print out result message as series of steps
;
        mov     eax, outmsg1
        call    print_string      ; print out first message
        mov     eax, [input1]     
        call    print_int         ; print out input1
        mov     eax, outmsg2
        call    print_string      ; print out second message
        mov     eax, [input2]
        call    print_int         ; print out input2
        mov     eax, outmsg3
        call    print_string      ; print out third message
        mov     eax, ebx
        call    print_int         ; print out sum (ebx)
        call    print_nl          ; print new-line

        popa
        mov     eax, 0            ; return back to C
        leave                     
        ret

The asm_io file is located here: https://github.com/nateware/cpp/blob/master/assembly/asm_io.asm

With the use of djgpp mingw(prebuillt 12.2.0) to compile and NASM(2.16.01) as well for asm. The commands I've used include:

i586-pc-msdosdjgpp-gcc.exe -c driver.c
nasm -f coff first.asm
nasm -f coff asm_io.asm

For the final linking i used:

i586-pc-msdosdjgpp-gcc.exe -o first driver.o first.o asm_io.o

Additional things i have done:

Instead of using nasm -f coff first.asm i used nasm -f win32 first.asm
Instead of nasm -f coff asm_io.asm i used nasm -f win32 -d COFF_TYPE asm_io.asm
Finally i did gcc driver.o first.obj asm_io.obj -o first.exe

The following errors now arise:

6 architecture of input file `asm_io.obj' is incompatible with i386:x86-64 output
driver.o:driver.c:(.text+0xe): undefined reference to `asm_main'
asm_io.obj:asm_io.asm:(.text+0x10): undefined reference to `_scanf'
asm_io.obj:asm_io.asm:(.text+0x2a): undefined reference to `_printf'
asm_io.obj:asm_io.asm:(.text+0x41): undefined reference to `_printf'
asm_io.obj:asm_io.asm:(.text+0x52): undefined reference to `_getchar'
asm_io.obj:asm_io.asm:(.text+0x68): undefined reference to `_putchar'
asm_io.obj:asm_io.asm:(.text+0x7a): undefined reference to `_putchar'
asm_io.obj:asm_io.asm:(.text+0x149): undefined reference to `_printf'
asm_io.obj:asm_io.asm:(.text+0x16c): undefined reference to `_printf'
asm_io.obj:asm_io.asm:(.text+0x198): undefined reference to `_printf'
asm_io.obj:asm_io.asm:(.text+0x1bf): undefined reference to `_printf'
asm_io.obj:asm_io.asm:(.text+0x1d8): undefined reference to `_printf'

No matter what I have done to try and get the final exe, I've failed. Any help or something i am missing?

For Further Context: This is from the book PCASM by Paul Carter: https://github.com/nateware/cpp/blob/master/assembly/first.asm Included CDEHL header file: header file The assembly input\output file is located here:I/O


Solution

  • The easiest way to make examples of that book work on your system is using the 32-bit MinGW GCC. As soon as you have it set up, these commands work:

    gcc -c driver.c
    nasm -f win32 -o first.o first.asm
    nasm -f win32 -o asm_io.o asm_io.asm
    gcc -o first driver.o first.o asm_io.o
    first.exe
    

    If you get an error, please copy-paste all the commands you have run (including gcc -v), and the full output of each to your question, and then add a comment stating that you have extended the question.

    Before installing anything to your system (64-bit Windows), remove all of these: DJGPP, MinGW (32-bit and 64-bit), MinGW-w64, MSYS, MSYS2. You can keep NASM.

    You can get the 32-bit MinGW GCC by following any (one) of these methods:

    • Directly from MINGW32. (I think this one is easier.)

    • Installing MSYS2, setting the environment variable MSYS=MINGW32 (to select the MINGW32 environment), starting the MSYS2 shell window, installing GCC.

    Unfortunately I'm not able to help you with the installation beyond what I aready wrote. If you get stuck, ask a separate question on StackOverflow.

    If you are unsure whether your GCC is 32-bit or 64-bit, run gcc -v, and look at the line starting with Target:. If it contains 64, then it's 64-bit. If it contains i386, i486, i586 or i686, then it's 32-bit. You need 32-bit. If you get 64-bit, then you've installed the wrong GCC, you have to uninstall it, and install the right one. If needed, ask a separate question on StackOverflow.

    Don't use DJGPP, because it creates DOS .exe files, and those don't work on 64-bit Windows systems such as your system. (You may get an error about missing 16-bit support. It doesn't matter that your .asm files have 32-bit code, DOS .exe files won't work on your system, and DJGPP is not able to create anything else.)

    For this project, don't use 64-bit GCC (e.g. in MinGW-w64), because it generates 64-bit Windows .exe files, which require 64-bit .asm files, and your book contains only 32-bit .asm files.