我想把c代码转换成MIPS,它可以在QTSpim上运行。例如:转换
#include<stdio.h>
int main() {
printf("Hello, World!");
return 0;
}转到
.data
msg: .asciiz "Hello World"
.extern foobar 4
.text
.globl main
main: li $v0, 4 # syscall 4 (print_str)
la $a0, msg # argument: string
syscall # print the string
lw $t1, foobar
jr $ra # retrun to caller我在我的苹果电脑上试用了一下gcc的-S helloWorld.c,然后我得到了如下的helloWorld.s:
.section __TEXT,__text,regular,pure_instructions
.build_version macos, 11, 0 sdk_version 11, 3
.globl _main ## -- Begin function main
.p2align 4, 0x90
_main: ## @main
.cfi_startproc
## %bb.0:
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset %rbp, -16
movq %rsp, %rbp
.cfi_def_cfa_register %rbp
subq $16, %rsp
movl $0, -4(%rbp)
leaq L_.str(%rip), %rdi
movb $0, %al
callq _printf
xorl %ecx, %ecx
movl %eax, -8(%rbp) ## 4-byte Spill
movl %ecx, %eax
addq $16, %rsp
popq %rbp
retq
.cfi_endproc
## -- End function
.section __TEXT,__cstring,cstring_literals
L_.str: ## @.str
.asciz "Hello, World!"
.subsections_via_symbols我已经搜索了一些,但没有明确的答案。我对MIPS很陌生,因为我发现有很多MIPS的汇编语言?任何解释或解决方案都将不胜感激。提前谢谢。
发布于 2021-06-04 22:52:53
流行的模拟器MARS和QTSpim都有自己的环境,也就是说,它们没有printf和getChar。
相反,它们使用syscall进行I/O。syscall不是一个完整的编程环境,所以虽然它们可以做printf可以做的一些事情,但它们没有很多特性(例如,sprintf的特性完全缺失)。
以下是MARS中可用的syscall的文档(QTSPim支持第一组syscall,但不支持编号较高的syscall)。
http://courses.missouristate.edu/kenvollmar/mars/help/syscallhelp.html
要将printf语句转换为syscall形式,我们需要进行一些分解:
printf ( "hello %d\n", 10 ); 会变成三个不同的syscall:
接下来你需要理解的是,系统调用本身有点像函数调用,所以我们需要理解参数传递。系统调用在$v0中接受一个函数代码,该代码说明要执行什么操作。每个函数都解释$a0、$a1等的值。根据上面链接中的规范。
为了传递参数,需要将值放置到寄存器中,但是将值放置到寄存器中的顺序是任意的-因此,只要$v0的值为4,并且$a0在内存中有一个指向字符串的指针,那么syscall指令就会打印该字符串。
我不知道任何编译器会自动将printf语句转换成MARS/QTSpim所需的形式。然而,可用的编译器(例如,godbolt.org有几个MIPS编译器可用)通常很好地显示非I/O C语句和表达式的汇编翻译(尽管它们的输出对于模拟器想要的东西来说是嘈杂的)。
模拟器的编程通常被简化。局部变量,特别是数组,通常作为全局变量来完成,因为在堆栈上创建数组需要额外的工作和对堆栈处理和堆栈偏移的理解,而全局变量很容易用名称来声明。
https://stackoverflow.com/questions/67839233
复制相似问题