2016-11-08 45 views
0

長時間潛伏者,首次提問者。我剛剛開始使用MIPS,並且被一個項目弄糊塗了。這個任務是創建一個程序,它接受一個整數輸入並輸出基數2到16的ascii轉換。我想,如下所示,我已經計算出了初始轉換,但基數循環仍然避開了我。任何幫助將不勝感激!itoa整數與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代碼,我有我只需要翻譯,但我不能確定如何爲基數的循環工作

#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] = "ABCDEF"; 

    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

如何循環彙編:

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 < = 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 

BTW,您是否手動輸入該asm源,或者如何發生這種情況:或者如何發生這種情況:

bne $to,$zero,order #If t0<>0 go to order 

$to而不是$t0

您應該從實際來源複製源代碼,以便任何嘗試回答您的問題的人都可以重複您的步驟並獲得相同的問題。這個可能甚至不能編譯?