【发布时间】:2016-09-13 06:02:08
【问题描述】:
所以这里的代码如愿:
程序 1
.text
.globl main
main:
li $t0, 10
mtc1 $t0, $f12
cvt.s.w $f12, $f12 # 10.0 as single in $f12
jal printFloat
li $v0, 4001 #sys_exit
syscall
printFloat:
addi $sp, $sp, -4 #opens the stack frame
sw $ra, 0($sp) #saves the return adress
cvt.d.s $f12, $f12 #converts the single to double
la $a0, strDouble #arguments needed for printf ("%f" in $a0, upper 32 bit of the float in $a2, lower ones in $a1)
mfc1 $a1, $f12
mfc1 $a2, $f13
jal printf
jal fflush
la $a1, strBreakLine #arguments needed for printf (Adress of String in $a1, "%s" in $a0)
la $a0, strStringOut
jal printf
jal fflush
lw $ra, 0($sp) #restores the return adress
addi $sp, $sp, 4 #pops the stack frame
jr $ra
.data
strDouble: .asciiz "%f"
strStringOut: .asciiz "%s"
strBreakLine: .asciiz "\n"
phm15fix@ci20:~$ gcc -o test -g test1.s
phm15fix@ci20:~$ ./test
10.000000
程序 2
.text
.globl main
main:
li $t0, 10
mtc1 $t0, $f12
cvt.s.w $f12, $f12 # 10.0 as single in $f12
jal printFloat
li $v0, 4001 #sys_exit
syscall
printFloat:
addi $sp, $sp, -4 #opens the stack frame
sw $ra, 0($sp) #saves the return adress
cvt.d.s $f12, $f12 #converts the single to double
la $a0, strDouble #arguments needed for printf ("%f" in $a0, upper 32 bit of the float in $a2, lower ones in $a1)
mfc1 $a1, $f12
mfc1 $a2, $f13
jal printf
jal fflush
jal printNewLine
lw $ra, 0($sp) #restores the return adress
addi $sp, $sp, 4 #pops the stack frame
jr $ra
printNewLine:
addi $sp, $sp, -4 #opens the stack frame
sw $ra, 0($sp) #saves the return adress
la $a1, strBreakLine #arguments needed for printf (Adress of String in $a1, "%s" in $a0)
la $a0, strStringOut
jal printf
jal fflush
lw $ra, 0($sp) #restores the return adress
addi $sp, $sp, 4 #pops the stack frame
jr $ra
.data
strDouble: .asciiz "%f"
strStringOut: .asciiz "%s"
strBreakLine: .asciiz "\n"
phm15fix@ci20:~$ gcc -o test -g test1.s
phm15fix@ci20:~$ ./test
10.000000
Bus error
程序 3
.text
.globl main
main:
li $t0, 10
mtc1 $t0, $f12
cvt.s.w $f12, $f12 # 10.0 as single in $f12
jal function
li $v0, 4001 #sys_exit
syscall
function:
addi $sp, $sp, -4 #opens the stack frame
sw $ra, 0($sp) #saves the return adress
jal printFloat
lw $ra, 0($sp) #restores the return adress
addi $sp, $sp, 4 #pops the stack frame
jr $ra
printFloat:
addi $sp, $sp, -4 #opens the stack frame
sw $ra, 0($sp) #saves the return adress
cvt.d.s $f12, $f12 #converts the single to double
la $a0, strDouble #arguments needed for printf ("%f" in $a0, upper 32 bit of the float in $a2, lower ones in $a1)
mfc1 $a1, $f12
mfc1 $a2, $f13
jal printf
jal fflush
jal printNewLine
lw $ra, 0($sp) #restores the return adress
addi $sp, $sp, 4 #pops the stack frame
jr $ra
printNewLine:
addi $sp, $sp, -4 #opens the stack frame
sw $ra, 0($sp) #saves the return adress
la $a1, strBreakLine #arguments needed for printf (Adress of String in $a1, "%s" in $a0)
la $a0, strStringOut
jal printf
jal fflush
lw $ra, 0($sp) #restores the return adress
addi $sp, $sp, 4 #pops the stack frame
jr $ra
.data
strDouble: .asciiz "%f"
strStringOut: .asciiz "%s"
strBreakLine: .asciiz "\n"
每个程序的结尾都是特定的输出。
第一个程序运行良好。 在第二个程序中,我制作了一个额外的功能来打印新行。如果我运行它,我会收到“总线错误”。
在第三个程序中,我创建了一个虚拟函数来模拟另一个堆栈级别。 还有一个“总线错误”,我要打印的号码没有打印。
我认为我们的堆栈有问题。
我使用了调试器,如果我从堆栈加载返回地址,我的 $ra 中的地址错误,我不知道为什么。如果它跳转到这个地址,我会得到“总线错误”。
以下是函数:
PRINT_DOUBLE:
addi $sp, $sp, -4
sw $ra, 0($sp)
la $a0, strDouble
mfc1 $a1, $f12
mfc1 $a2, $f13
jal printf
nop
# lw $a0, stdout
# jal fflush
jal BREAK_LINE
lw $ra, 0($sp)
addi $sp, $sp, 4
jr $ra
BREAK_LINE:
addi $sp, $sp, -4
sw $ra, 0($sp)
la $a0, strBreakLine
jal PRINT_STRING
lw $ra, 0($sp)
addi $sp, $sp, 4
nop
jr $ra
PRINT_STRING:
addi $sp, $sp, -4
sw $ra, 0($sp)
add $a1, $a0, $zero
la $a0, strStringOut
jal printf
la $a0, stdout
lw $a0, 0($a0)
jal fflush
lw $ra, 0($sp)
addi $sp, $sp, 4
nop
jr $ra
【问题讨论】:
-
这可能与您的问题无关,但您为什么使用
printf("%s", "\n");而不仅仅是printf("\n");(或者更简单:puts("");)? -
通常,除非您使用最小的代码示例将代码放入实际问题中,否则 SO 人将非常无助。 Pastebin 和其他链接没有帮助。
-
另外,使用调试器至少查明错误的确切位置。
标签: assembly stack mips mips32