做伪代码翻译成汇编语言时,遇到了如下错误:
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++文件的目标文件。