长时间潜伏,第一次问问。我刚开始使用MIPS并且对项目感到有些困惑。赋值是创建一个程序,它接受一个整数输入并输出基数2到16的ascii转换。我认为,如下所示,我已经找到了初始转换但是基数循环仍然逃避了我。任何帮助将不胜感激!
.data
str: .space 128 # space for the output string
# examples of macros, for printing.
.macro print_int (%x)
add $a0, $zero, %x
li $v0, 1
syscall
.end_macro
.macro print_str (%x)
la $a0, %x
li $v0, 4
syscall
.end_macro
# str address is in a register
.macro print_str_r (%x)
add $a0, $zero, %x
li $v0, 4
syscall
.end_macro
.text # Code segment
.globl main # declare main to be global
main:
print_str(name) # use macro
# You can read the number with a system call
#li $s0, 49
#li $v0, 5 #read an integer
#syscall
#move $s0, $v0 #save the user input
li $s0, 0xFFFFFFFF # pseudo instruction for loading large constant
la $s1, str
# You need to construct a loop to use radices 2 .. 16
# for $s2 = 2, $s2 < 17, $s2 ++
li $s2, 2
#call itoa
move $a0, $s0 #save n to $s0
move $a1, $s1
move $a2, $s2
jal itoa
# print the radix
print_int($s2) # note $a0 and $v0 are overwritten
print_str(msg_tab)
print_str_r($s1)
print_str(msg_nl)
# Need to jump back to the beginning of the loop
Exit: li $v0,10 # System call, type 10, standard exit
syscall # ...and call the OS
# function itoa (value, buffer, radix)
# it only returns '0' for now.
# you can return an empty string '' if the radix is not supported.
itoa:
addi $t0,$zero,10 # t0=10
addi $t1,$t1,a0 # t1=a0
Loop:
div $t1,$t0 #t1/10
mflo $t1 #t1 = quotient
mfhi $t2 #t2 =remainder
addi $t2,$t2,0x30 #Convert to ASCII
addi $sp,$sp,-1 #Make space for 1 byte in the stack
sb $t2,0($sp) #Push t2 in the stack
addi $v0,$v0,1 #v0=v0+1
bne $t1,$zero,Loop #If t1<>0 go to Loop
order:
sw $t0,$v0 #t0=v0
lb $t1,0($sp) #pop the last byte for the stack
addi $sp,$sp,1 #Reduce the stack size by 1 byte
add $t2,$v0,-$t0 #t2=v0-t0
sb $t1,$t2($a1) # savebyte to the proper location of memory
addi $t0,$t0,-1 #t0=t0-1
bne $to,$zero,order #If t0<>0 go to order
sb 0x0,$v($a0) # add null character to the end of the string
jr $ra
编辑: 以下是我需要翻译的一些C代码,但我不确定如何使Radix循环工作
#include <stdio.h>
#include <stdlib.h>
char * my_itoa(unsigned int v, char *p, int r)
{
unsigned int c;
char *p_old, *q;
static char hexdigits[32] = "0123456789ABCDEF";
if (r < 2 || r > 16) {
*p = 0;
return p;
}
if (v == 0) { // return '0'
p[0] = '0';
p[1] = 0; // end of the string.
return p;
}
p_old = p; // save the starting address of the buffer
// doing the conversion
// p points to the location where to store the next character
while (v > 0) {
// You can get both c an v with ONE MIPS instruction
c = v % r;
v = v / r;
*p = hexdigits[c];
p ++; // increment p
}
*p = 0; // end of the string
// reverse the string
// q points to the head and p points to the tail
q = p_old;
p = p - 1;
while (q < p) {
// swap *q and *p
c = *q;
*q = *p;
*p = c;
// increment q and decrement p
q ++;
p --;
}
return p_old;
}
char buf[128];
int main (int argc, char **argv)
{
int r;
unsigned int n = (argc > 1) ? atoi(argv[1]) : (unsigned int)-1;
for (r = 2; r <= 16; r ++)
printf("r=%d\t%s\n", r, my_itoa(n, buf, r));
return 0;
}
答案 0 :(得分:0)
如何在汇编程序中循环:
define_some_loop_label_at_first_instruction_of_loop:
; first instruction of loop
; ... other part of loop (can also send execution completely elsewhere)
; but should return back into loop (or you need to have duplicate loop test)
; end of loop, do the "loop test"
; (here you also may want to do things like increment loop counter, etc)
; calculate the loop-exit expressions, if not true
; jump to define_some_loop_label_at_first_instruction_of_loop
在您的情况下,您似乎在$s2
中有基数值。
评论说:
# for $s2 = 2, $s2 < 17, $s2 ++
哪个是正确的,但不准确,你想循环到$ s2&lt; = 16。 所以应该是这样的:
load s2 with 2
radix_loop:
... do the stuff (s2 contains radix value)
++s2
test s2 against 16
when less or equal, jump to radix_loop
; on MIPS the test + jump can be single (pseudo) instruction
; similar to the "bne $t1,$zero,Loop" in your other code
; here radix is 17 -> continue with any "exit" code you wish
顺便说一句,您是否手动输入了asm来源,或者如何发生这种情况:
bne $to,$zero,order #If t0<>0 go to order
($to
代替$t0
)
您应该只从实际来源复制来源,因此任何尝试回答您问题的人都可以重复您的步骤并遇到同样的问题。这个可能甚至无法编译?