1

I'm trying to learn some assembly code and I'm following a tutorial proposed by a book, I've got a C++ code defined as follows (Ch02_01.cpp) :

#include <iostream>


using namespace std;

extern "C" int IntegerAddSub_(int a, int b, int c, int d);
int main() {
    int a, b, c, d, result;
    a = 101;  b = 34; c = -190; d = 25;
    result = IntegerAddSub_(a, b, c, d);
    cout << "result = " << result << n1;
    return 0;
}

Knowing that The function IntegerAddSub_ is defined in an assembly file (asm extension) in the folder as follows (Ch02_01.asm) :

; extern "C" int IntegerAddSub_(int a, int b, int c, int d);

        .code
IntegerAddSub_ proc
; Calculate a + b + c -d
        mov eax, ecx      ;eax = a
        add eax, edx      ;eax = a + b
        add eax, r8d      ;eax = a + b + c
        sub eax, r9d      ;eax = a + b + c - d
        ret               ; return result to caller

IntegerAddSub_ endp
        end

Error message :

Error message :
/home/.local/share/JetBrains/Toolbox/apps/CLion/ch-0/222.3345.126/bin/cmake/linux/bin/cmake --build /home/Assembly/cmake-build-debug --target Assembly -j 16
[1/1] Linking CXX executable Assembly
FAILED: Assembly 
: && /usr/bin/c++ -g  CMakeFiles/Assembly.dir/Ch02_01.cpp.o -o Assembly   && :
/usr/bin/ld: CMakeFiles/Assembly.dir/Ch02_01.cpp.o: in function `main':
/home/Assembly/Ch02_01.cpp:25: undefined reference to `IntegerAddSub_'
collect2: error: ld returned 1 exit status
ninja: build stopped: subcommand failed.

I think the semantics of the error is simply that the C++ file did not recognize the function defined in the assembler file.

According to the exchanges in the comments, i'll add the following informations: I'am using CLION (From Jetbrains) and here is my CMakeLists.txt

cmake_minimum_required(VERSION 3.23)
project(Assembly)

set(CMAKE_CXX_STANDARD 14)
set ( SOURCES
      Ch02_01.asm
    )
add_executable(Assembly
        Ch02_01.cpp)

And I don't know how to compile that using g++, it never recognizes the function from the ASM file, how can I successfully compile that, please? I am in Ubuntu. Thanks

E Epsylon
  • 56
  • 1
  • 6
  • How do you know "it never recognizes the function from the ASM file"? Is there an error message you want to share? – Erik Eidt Aug 01 '22 at 14:01
  • I have just taken my first steps on C++ and assembler, it's Clion (Jetbrains IDE) who gives me the possibility to execute that script and i don't know what build command it has used for that . – E Epsylon Aug 01 '22 at 14:01
  • 1
    I think such stuff would be better to learn from the command line – RoQuOTriX Aug 01 '22 at 14:02
  • Error message : /home/.local/share/JetBrains/Toolbox/apps/CLion/ch-0/222.3345.126/bin/cmake/linux/bin/cmake --build /home/Assembly/cmake-build-debug --target Assembly -j 16 [1/1] Linking CXX executable Assembly FAILED: Assembly : && /usr/bin/c++ -g CMakeFiles/Assembly.dir/Ch02_01.cpp.o -o Assembly && : /usr/bin/ld: CMakeFiles/Assembly.dir/Ch02_01.cpp.o: in function `main': /home/Assembly/Ch02_01.cpp:25: undefined reference to `IntegerAddSub_' collect2: error: ld returned 1 exit status ninja: build stopped: subcommand failed. – E Epsylon Aug 01 '22 at 14:02
  • 3
    Since your are using CMake I believe it would be helpful to post your CMakeLists.txt to see how you added the .asm file – drescherjm Aug 01 '22 at 14:04
  • I've added the error to the question . – E Epsylon Aug 01 '22 at 14:04
  • 3
    The `.asm` file should be part of the `add_executable` stanza. There is nothing special about the `SOURCES` variable. – Botje Aug 01 '22 at 14:08
  • @Botje, add_executable(Assembly Ch02_01.asm Ch02_01.cpp) The error still persists :( – E Epsylon Aug 01 '22 at 14:12
  • Can you compile the assembler file into an object if you use `g++` manually on the command prompt? If so, what command line are you using? – Ted Lyngmo Aug 01 '22 at 14:23
  • @TedLyngmo, ok how should i run it ? a simply g++ ./Ch02_01.cpp ? – E Epsylon Aug 01 '22 at 14:25
  • 2
    While you tagged `nasm` that code looks more like `masm`. Also, your default cmake might not even know what to do with a `.asm` file anyway. – Jester Aug 01 '22 at 14:25
  • 2
    At the very least you are missing the `enable_languages(ASM_NASM)` statement such that CMake knows how to compile it. – Botje Aug 01 '22 at 14:25
  • Oh, nasm. If you try `nasm -MD Ch02_01.asm.o.d -MT Ch02_01.asm.o -f elf64 -o Ch02_01.asm.o Ch02_01.asm` - (replace `elf64` if needed) does it compile? – Ted Lyngmo Aug 01 '22 at 14:29
  • Won't the object files have the same name? What happens if you rename Ch02_01.asm to something else? – TonyK Aug 01 '22 at 14:41
  • @Botje your solution solved the problem as well, can you comment it down please? it could help someone else :) – E Epsylon Aug 01 '22 at 14:41

1 Answers1

5

You need to tell CMake that the project includes code too - or if that's what it actually is.

Example:

cmake_minimum_required(VERSION 3.22)
project(Assembly CXX ASM_NASM) # or perhaps it should be ASM_MASM

set(CMAKE_CXX_STANDARD 14)

add_executable(Assembly Ch02_01.asm Ch02_01.cpp)

This makes it at least try to compile the asm file, but for me it fails:

[ 33%] Building ASM_NASM object CMakeFiles/Assembly.dir/Ch02_01.asm.o
/home/ted/proj/stackoverflow/assembly/Ch02_01.asm:3: warning: label alone on a line without a colon might be in error [-w+label-orphan]
/home/ted/proj/stackoverflow/assembly/Ch02_01.asm:4: error: parser: instruction expected
/home/ted/proj/stackoverflow/assembly/Ch02_01.asm:12: error: label `IntegerAddSub_' inconsistently redefined
/home/ted/proj/stackoverflow/assembly/Ch02_01.asm:4: info: label `IntegerAddSub_' originally defined here
/home/ted/proj/stackoverflow/assembly/Ch02_01.asm:12: error: parser: instruction expected
/home/ted/proj/stackoverflow/assembly/Ch02_01.asm:13: warning: label alone on a line without a colon might be in error [-w+label-orphan]
make[2]: *** [CMakeFiles/Assembly.dir/build.make:76: CMakeFiles/Assembly.dir/Ch02_01.asm.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:83: CMakeFiles/Assembly.dir/all] Error 2
make: *** [Makefile:91: all] Error 2
Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108
  • Exactly, so I've errors in my assembly code, thanks a lot ! – E Epsylon Aug 01 '22 at 14:42
  • @EEpsylon You're welcome. Did you try with `ASM_MASM` too? I don't have a [tag:masm] compiler so I can't verify it myself. – Ted Lyngmo Aug 01 '22 at 14:42
  • I think yes, because i've added enable_language(ASM_NASM) (which is not exactly written as the same way you did, but it contains asm_nasm) and i've got the same errors. – E Epsylon Aug 01 '22 at 14:45
  • Yes, but did you try `ASM_MASM` ? Note that there is an `M` instead of an `N` first. It's the Microsoft Macro Assembler. – Ted Lyngmo Aug 01 '22 at 14:45
  • Ah sorry, i didn't get the point in your first message, yes i've tried MASM instead of NASM, and it returns an sh error, "/bin/sh: 1: ml: not found", what about you ? – E Epsylon Aug 01 '22 at 14:49
  • 2
    Ah, yes, that's what I get too because I don't have a [tag:masm] compiler installed. – Ted Lyngmo Aug 01 '22 at 14:50
  • 2
    @EEpsylon and TedLyngmo: this is MASM source code. The primary sign is `foo proc` / ... / `endp` instead of NASM/FASM `global foo` / `foo:`. Also `.code` instead of `section .text`, and an `end` directive on the last line. It looks valid for x86-64 MASM (or JWASM) using the Windows x64 calling convention. You could optimize by replacing mov/add with `lea eax, [rcx+rdx]`, but missed optimizations / intentionally simplified code for beginners is irrelevant to having it build + link. – Peter Cordes Aug 01 '22 at 19:31
  • 1
    @EEpsylon: The paths you mention in your question look like non-Windows. Non-Windows systems use a different calling convention (args in RDI, RSI, RDX, RCX, R8, R9). Even if you used JWASM to build this into an ELF `.o` on Linux (or MachO64 `.o` on MacOS), it would read the wrong arg registers and return a wrong number when you ran it. [Why does Windows64 use a different calling convention from all other OSes on x86-64?](https://stackoverflow.com/q/4429398) And see Agner Fog's calling convention guide: https://agner.org/optimize . And other links in https://stackoverflow.com/tags/x86/info – Peter Cordes Aug 01 '22 at 19:38
  • Thanks @PeterCordes ! I have never used NASM or MASM myself so I wasn't sure :) – Ted Lyngmo Aug 01 '22 at 19:40
  • @EEpsylon: I assume you're a beginner with asm in general, or for x86-64 at least. **You're going to need a tutorial for your OS, not just for x86-64**. And for an assembler you want to use, probably NASM or GAS. Asm is the least portable language, and there are multiple incompatible assembly languages (NASM, MASM, GAS, Go/Plan9) for x86-64. FASM is a lot like NASM but has some differences, e.g. in what `equ` vs. `=` means for assemble-time macros / int constants. (Most other ISAs only have one assembly langauge, although different calling conventions / ABIs across systems is a thing.) – Peter Cordes Aug 01 '22 at 19:44