多MIPS文件标签调用问题:如何让文件兼具独立运行与被调用能力
问题
我有两个MIPS汇编文件,需要在文件A中调用文件B的代码完成计算,但碰到了麻烦:
- 试过用
.globl指令让A调用B的test标签,但因为两个文件都有main标签,编译直接报错。 - 删掉文件B的
main后,A能正常调用B,但B没法单独运行了。
想知道有没有办法:要么不依赖main标签执行文件(比如指定其他入口点),要么不用改文件B,让它既能单独跑又能被A调用?
补充代码
文件A代码
.data .globl main .text main: ori $a1, $0 , 0x9384 # N = 0x00009384 sll $a1, $a1, 16 # N = 0x93840000 ori $a1, $a1, 0x9ca7 # N = 0x93849ca7; N input ori $t6, $0 , 0x0123 # M = 0x00000011 sll $t6, $t6, 16 # M = 0x00110000 ori $t6, $t6, 0x4567 # M = 0x00112233; M input ori $t7, $0 , 0x8C8D # K = 0x00008C8D sll $t7, $t7, 16 # K = 0x8C8D0000 ori $t7, $t7, 0x9129 # K = 0x8C8D9129; K constant beq $0, $0, test # 想调用B中的test addu $t5, $t1, $0 ... 后续代码
文件B代码
.data .text test: sll $t6, $t6, 1
注:调用完B的代码后,要回到A中beq后面的addu指令处理结果。
解决方案
先纠正一个调用错误
你现在用beq $0, $0, test是无条件跳转,但不会保存返回地址,跑完test后根本回不到A的后续代码。正确的做法是用jal test(跳转并链接),它会把当前指令的下一条地址存在$ra寄存器里,同时在文件B的test末尾加jr $ra指令,让程序跳回A的addu位置。
方案1:让B既能独立运行又能被A调用
方法A:给B加条件编译的main入口
修改文件B,添加一个可选的main入口,只有单独编译B时才生效,同时把test声明为全局符号:
.data .text .globl test # 必须声明为全局,A才能找到 test: sll $t6, $t6, 1 jr $ra # 加返回指令,回到A的调用点 # 只有单独运行B时才启用的main入口 #ifdef STANDALONE .globl main main: # 这里写B独立运行时的初始化代码,比如设置测试值 ori $t6, $0, 0x1234 jal test # 调用自己的test # 执行完后退出程序 li $v0, 10 syscall #endif
- 单独编译运行B时,加上
-DSTANDALONE参数:mips-as -o b.o b.s -DSTANDALONE mips-ld -o b b.o - 和A一起编译时,不加这个参数,链接器会自动用A的
main:mips-as -o a.o a.s mips-as -o b.o b.s mips-ld -o a a.o b.o
方法B:不修改B,用链接选项指定入口
如果不想改B的代码,单独运行B时,用链接器的-e选项指定test作为入口点:
mips-as -o b.o b.s mips-ld -o b b.o -e test
但要注意:这种方式下,B的test运行完后没有退出逻辑,会跑到未知内存区域导致崩溃。所以最好还是在test末尾加一句退出指令(li $v0,10; syscall),或者在模拟器里手动终止。
方案2:不依赖main标签执行文件
所有MIPS链接器都支持用-e选项指定任意入口标签,不管有没有main。如果用的是MARS、SPIM这类模拟器,也可以在模拟器的设置里直接指定入口标签(比如MARS在Settings菜单中修改入口点配置)。
内容的提问来源于stack exchange,提问作者Emily
相关产品推荐
相关产品推荐

