itoa与Ascii的整数,具有不同的基数

时间:2016-11-08 00:32:40

标签: assembly ascii mips

长时间潜伏,第一次问问。我刚开始使用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;
}

1 个答案:

答案 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

您应该只从实际来源复制来源,因此任何尝试回答您问题的人都可以重复您的步骤并遇到同样的问题。这个可能甚至无法编译?