ubuntu18.04 makefile:13: recipe for target 'run' failed

做伪代码翻译成汇编语言时,遇到了如下错误:

li***@VirtualBox:~/lab2/assignment$ make run
>>> begin test
makefile:13: recipe for target 'run' failed
make: *** [run] 段错误 (core dumped)

在网上找了很多办法都解决不了,可以告诉我究竟是哪里出错了吗?
makefile文件内容如下:

TARTGET = test

AS = nasm
CXX = g++

ASM_FILE = $(wildcard *.asm)
CXX_FILE = $(wildcard *.cpp)

ALL_OBJ += $(ASM_FILE:%.asm=%.o)
ALL_OBJ += $(CXX_FILE:%.cpp=%.o)

run:
    @rm -rf *.o
    @nasm -f elf32 $(ASM_FILE)
    @g++ -m32 -g -c $(CXX_FILE)
    @g++ -m32 -o $(TARTGET) $(ALL_OBJ)
    @./$(TARTGET)
clean:
    @rm -rf *.o

我自己编写的汇编文件student.asm如下:

; If you meet compile error, try 'sudo apt install gcc-multilib g++-multilib' first

%include "head.include"
; you code here
.data:
string db 1024 dup(0)
count equ $-string

.code:
mov ecx,if_flag
mov ebx,string

your_if:
mov eax,a1
cmp eax,12
jnl ope1
mov ebx,2
idiv ebx
inc eax
jmp Exit

ope1:
cmp eax,24
jng ope2
mov edx,eax
neg eax
add eax,24
imul eax,edx
jmp Exit

ope2:
shl eax,4
jmp Exit

Exit:
ret

your_while:
mov ecx,a2
mov ebx,while_flag
Loop:
call my_random
mov [ebx+ecx-12],eax
sub ecx,1
cmp ecx,12
jge Loop
mov eax,ebx
ret

%include "end.include"

your_function:
mov edx,0
mov ebx,string
for:
cmp word [ebx+edx],'\0'
je exit
add edx,1
pushad
mov eax,[ebx+edx]
push eax
call print_a_char
pop eax
popad
jmp for
exit:
ret

测试文件test.cpp代码如下:

#include 

#include 

#include 

#include 



#define RAND_WIDTH 26

extern "C" void student_function();

extern "C" void your_function();

int if_flag, a1, a2;

const char *your_string = "Mr.Chen, students and TAs are the best!\n";

char *while_flag, *random_buffer;


// THE ONLY CODE YOU CAN CHANGE IN THIS FILE!!!

void student_setting() {

    a1 = 24;

    a2 = 14;

}

extern "C" char my_random() {

    char c = rand() % (RAND_WIDTH) + 'a';

    random_buffer[a2 - 12] = c;

    return c;

}

extern "C" void print_a_char(char c) {

    std::cout << c;

}

void test_failed() {

            std::cout << ">>> test failed" << std::endl;

            exit(0);

}

int main() {

    student_setting();

    // init

    std::cout << ">>> begin test" << std::endl;

    if_flag = 0;



    if(a2 >= 12) {

        while_flag = new char[a2 - 12 + 1];

        random_buffer = new char[a2 - 12 + 1];

        if(!while_flag || !random_buffer) {

            std::cout << "test can not run" << std::endl;

            exit(-1);

        }

        memset(while_flag, 0, a2 - 12 + 1);

        memset(random_buffer, 0, a2 - 12 + 1);

    }
    student_function();

    if(a1 < 12) {

        if (if_flag != a1 / 2 + 1) {

            test_failed();

        }

    } else if(a1 < 24) {

        if (if_flag != (24 - a1) * a1) {

            test_failed();

        }

    } else {

        if (if_flag != a1 << 4) {

            test_failed();

        }
    }
    std::cout << ">>> if test pass!" << std::endl;
    if(strcmp(while_flag, random_buffer) == 0 && a2 < 12) {

        std::cout << ">>> while test pass!" << std::endl;

    } else {

        test_failed();

    }
    your_function();

}

head.include代码如下:

global student_function
global your_function

extern a1
extern a2
extern my_random
extern your_string
extern if_flag
extern while_flag
extern print_a_char

student_function:
    pushad

end.include代码如下:

student_function_end:
    popad
    ret

已解决,汇编文件出了问题,导致makefile出现段错误

参考GPT和自己的思路:

根据您提供的信息,看起来类似于您的makefile文件中的某些语句引起了对'test'目标的执行失败。

具体来说,对于'test'目标和执行下列语句时发生了段错误:

@g++ -m32 -o $(TARTGET) $(ALL_OBJ)
@./$(TARTGET)

可能的原因是在编译和链接代码时出现了一些错误,导致生成的可执行文件包含一些不正确的指令,从而导致程序在执行时崩溃。

为了进一步了解问题的原因,您可以尝试以调试模式重新编译您的代码,并在程序崩溃时使用GDB调试器跟踪堆栈跟踪信息。

此外,您可能还需要查看您的代码中是否存在其他更明显的错误,例如未定义的符号、语法错误等。

根据提示信息,是在执行makefile里的run规则时出现了段错误(Core Dumped)。需要进一步排查错误出现的原因。
建议打印出 makefile 执行时的详细信息,可以在命令前加上 @ 前缀,例如:@g++ -m32 -o $(TARTGET) $(ALL_OBJ)。这样可以输出每次执行的命令,方便进行调试。
另外,建议先运行 nasm 和 g++ 命令,分别将 student.asm 和 test.cpp 编译成目标文件 student.o 和 test.o,再手动链接生成可执行文件 test,看看能否正常运行。如果可以正常运行,则问题可能出现在 Makefile 的 run 规则上,反之,则排查汇编和 C++ 代码是否存在语法或逻辑错误。
最后,还需要检查 student.asm 文件中的标签是否正确以及段落是否对齐等细节问题。

makefile里的tab字符必须是真的tab字符,不能用空格代替。

该回答引用GPTᴼᴾᴱᴺᴬᴵ
在您的Makefile文件中,第13行的规则 run: 应该在 ASM_FILE 和 CXX_FILE 被定义之后,才能使用 $(ASM_FILE) 和 $(CXX_FILE) 的值。但是您的定义顺序是错误的,导致这些变量没有被正确地赋值。

为了解决这个问题,您可以将 ASM_FILE 和 CXX_FILE 的定义移到 run: 的前面,或者将 run: 的定义移到文件末尾。例如:

TARGET = test

AS = nasm
CXX = g++

ASM_FILE = $(wildcard *.asm)
CXX_FILE = $(wildcard *.cpp)

ALL_OBJ += $(ASM_FILE:%.asm=%.o)
ALL_OBJ += $(CXX_FILE:%.cpp=%.o)

all: $(TARGET)

$(TARGET): $(ALL_OBJ)
    $(CXX) -m32 -o $@ $^

%.o: %.asm
    $(AS) -f elf32 -o $@ $<

%.o: %.cpp
    $(CXX) -m32 -g -c $< -o $@

run:
    @rm -rf *.o $(TARGET)
    @make all
    @./$(TARGET)

clean:
    @rm -rf *.o $(TARGET)

在这个示例Makefile中,我们将 run: 的定义移到了文件末尾,并将 ASM_FILE 和 CXX_FILE 的定义移到了文件顶部。此外,我们还添加了两个模式规则来构建汇编文件和C++文件的目标文件。