Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
mips中的Sprintf_Mips_Printf - Fatal编程技术网

mips中的Sprintf

mips中的Sprintf,mips,printf,Mips,Printf,所以我尝试在MIPS中创建Sprintf。问题是,我不知道如何处理%d、%c等的所有情况 所以,即使我真的能认出%我怎么能认出下一个字符呢?我的意思是,我在3美元的登记册中有%。 李:3美元,“%” 但是,对于$d、%c、%b等,我没有足够的寄存器 我如何检查它们 ###################################################################### # spf-main.s # # This is the main function th

所以我尝试在MIPS中创建Sprintf。问题是,我不知道如何处理%d、%c等的所有情况

所以,即使我真的能认出%我怎么能认出下一个字符呢?我的意思是,我在3美元的登记册中有%。 李:3美元,“%”

但是,对于$d、%c、%b等,我没有足够的寄存器

我如何检查它们

######################################################################
# spf-main.s
# 
# This is the main function that tests the sprintf function

# The "data" segment is a static memory area where we can 
# allocate and initialize memory for our program to use.
# This is separate from the stack or the heap, and the allocation
# cannot be changed once the program starts. The program can
# write data to this area, though.
    .data

# Note that the directives in this section will not be 
# translated into machine language. They are instructions 
# to the assembler, linker, and loader to set aside (and 
# initialize) space in the static memory area of the program. 
# The labels work like pointers-- by the time the code is 
# run, they will be replaced with appropriate addresses.

# For this program, we will allocate a buffer to hold the
# result of your sprintf function. The asciiz blocks will
# be initialized with null-terminated ASCII strings.

buffer: .space  20000           # 2000 bytes of empty space 
                    # starting at address 'buffer'

format: .asciiz "string: %s, unsigned dec: %u, hex: 0x%x, char: %c, dec: %d, bin: %b, percent: %%\n"
                    # null-terminated string of 
                    # ascii bytes.  Note that the 
                    # \n counts as one byte: a newline 
                    # character.
str:    .asciiz "thirty-nine"       # null-terminated string at
                    # address 'str'
chrs:   .asciiz " characters:\n"    # null-terminated string at 
                    # address 'chrs'
strpd:  .asciiz "%d"        # null-terminated string at 
strpc:  .asciiz "%c"        # null-terminated string at 
strpb:  .asciiz "%b"        # null-terminated string at     
strpu:  .asciiz "%u"        # null-terminated string at
strpx:  .asciiz "%x"        # null-terminated string at 
strpo:  .asciiz "%o"        # null-terminated string at 
strps:  .asciiz "%s"        # null-terminated string at 
strpp:  .asciiz "%%"        # null-terminated string at 
strpi:  .asciiz "%"     # null-terminated string at 



# The "text" of the program is the assembly code that will
# be run. This directive marks the beginning of our program's
# text segment.

    .text

# The sprintf procedure (really just a block that starts with the
# label 'sprintf') will be declared later.  This is like a function
# prototype in C.

    .globl sprintf

# The special label called "__start" marks the start point
# of execution. Later, the "done" pseudo-instruction will make
# the program terminate properly.   

main:
    addi    $sp,$sp,-36 # reserve stack space

    # $v0 = sprintf(buffer, format, str, 255, 255, 111, -255, -255)

    la  $a0,buffer  # arg 0 <- buffer
    la  $a1,format  # arg 1 <- format
    la  $a2,str     # arg 2 <- str

    addi    $a3,$0,255  # arg 3 <- 255
    sw  $a3,16($sp) # arg 4 <- 255

    addi    $t0,$0,111
    sw  $t0,20($sp) # arg 5 <- 111 ('o', as a character)

    addi    $t0,$0,-255
    sw  $t0,24($sp) # arg 6 <- -255

    addi    $t0,$0,255  
    sw  $t0,28($sp) # arg 7 <- 255

    sw  $ra,32($sp) # save return address
    jal sprintf     # $v0 = sprintf(...)

    # print the return value from sprintf using
    # putint()

    add $a0,$v0,$0  # $a0 <- $v0
    jal putint      # putint($a0)

    ## output the string 'chrs' then 'buffer' (which
    ## holds the output of sprintf)
    li  $v0, 4  
    la      $a0, chrs
    syscall
    #puts   chrs        # output string chrs

    li  $v0, 4
    la  $a0, buffer
    syscall
    #puts   buffer      # output string buffer

    addi    $sp,$sp,36  # restore stack
    li  $v0, 10     # terminate program
    syscall

# putint writes the number in $a0 to the console
# in decimal. It uses the special command
# putc to do the output.

# Note that putint, which is recursive, uses an abbreviated
# stack. putint was written very carefully to make sure it
# did not disturb the stack of any other functions. Fortunately,
# putint only calls itself and putc, so it is easy to prove
# that the optimization is safe. Still, we do not recommend 
# taking shortcuts like the ones used here.

# HINT: You should read and understand the body of putint,
# because you will be doing some similar conversions
# in your own code.

putint: addi    $sp,$sp,-8  # get 2 words of stack
    sw  $ra,0($sp)  # store return address

    # The number is printed as follows:
    # It is successively divided by the base (10) and the 
    # reminders are printed in the reverse order they were found
    # using recursion.

    remu    $t0,$a0,10  # $t0 <- $a0 % 10
    addi    $t0,$t0,'0' # $t0 += '0' ($t0 is now a digit character)
    divu    $a0,$a0,10  # $a0 /= 10
    beqz    $a0,onedig  # if( $a0 != 0 ) { 
    sw  $t0,4($sp)  #   save $t0 on our stack
    jal putint      #   putint() (putint will deliberately use and modify $a0)
    lw  $t0,4($sp)  #   restore $t0
                            # } 
onedig: move    $a0, $t0
    li  $v0, 11
    syscall         # putc #$t0
    #putc   $t0     # output the digit character $t0
    lw  $ra,0($sp)  # restore return address
    addi    $sp,$sp, 8  # restore stack
    jr  $ra     # return





    #sprintf!
#$a0 has the pointer to the buffer to be printed to
#$a1 has the pointer to the format string
#$a2 and $a3 have (possibly) the first two substitutions for the format string
#the rest are on the stack
#return the number of characters (ommitting the trailing '\0') put in the buffer

        .text

sprintf:
    addi $sp, $sp, -12
    sw $ra, 8($sp)
    sw $s1, 4($sp)
    sw $s2, 0($sp)







    li $a3, '%'     



        li      $s0, 0          # len = 1
        la      $s1, ($a1)        # s = str
test:
        lb      $s2, 0($s1)     # c = *s
        beqz    $s2, done       # if c == '\0', branch to "done"
     #   beq    $s2, $a3, percent

        addi    $s0, $s0, 1     # len = len + 1
        addi    $s1, $s1, 1     # s = s + 1
        j       test

percent:
     li $v0, 4    # print_string    
    la $a0, str 
    syscall



done:
     #   li      $v0, 1          # syscall code: print_int
     #   move    $a0, $s0
     #   syscall
       li      $v0, 11         # syscall code: print_char
        li      $a0, 10         # pass newline character
        syscall


        add $v0,$0, $s0
        lw $ra, 8($sp)
        lw $s1, 4($sp)
    lw $s2, 0($sp)
    addi $sp, $sp, 12

        jr      $ra
######################################################################
#spf main.s
# 
#这是测试sprintf函数的主要函数
#“数据”段是一个静态内存区域,我们可以在其中
#为我们的程序分配并初始化内存。
#这与堆栈或堆以及分配是分开的
#程序启动后无法更改。该程序可以
#不过,请将数据写入此区域。
.数据
#请注意,本节中的指令不适用
#翻译成机器语言。它们是指令
#到要搁置的汇编器、链接器和加载程序(以及
#初始化)程序静态内存区域中的空间。
#标签的工作方式类似于指针——在编写代码时
#运行时,它们将被相应的地址替换。
#对于这个程序,我们将分配一个缓冲区来保存
#sprintf函数的结果。asciiz区块将
#可以使用以null结尾的ASCII字符串初始化。
缓冲区:.空间20000#2000字节的空白空间
#从地址“缓冲区”开始
格式:.asciiz“字符串:%s,未签名的dec:%u,十六进制:0x%x,字符:%c,dec:%d,bin:%b,百分比:%%\n”
#以null结尾的字符串
#ascii字节。请注意
#\n计为一个字节:换行符
#性格。
str:.asciiz“三十九”#以null结尾的字符串位于
#地址'str'
chrs:.asciiz“字符:\n”#以null结尾的字符串位于
#地址“chrs”
strpd:.asciiz“%d”#以null结尾的字符串位于
strpc:.asciiz“%c”#以null结尾的字符串位于
strpb:.asciiz“%b”#以null结尾的字符串位于
strpu:.asciiz“%u”#以null结尾的字符串位于
strpx:.asciiz“%x”#以null结尾的字符串位于
strpo:.asciiz“%o”#以null结尾的字符串位于
strps:.asciiz“%s”#以null结尾的字符串位于
strpp:.asciiz“%%”#以null结尾的字符串位于
strpi:.asciiz“%”#以null结尾的字符串位于
#程序的“文本”是将
#被运行。该指令标志着我们的计划的开始
#文本段。
.文本
#sprintf过程(实际上只是一个以
#稍后将声明标签“sprintf”)。这就像一个函数
#原型用C。
环球斯普林特酒店
#名为“开始”的特殊标签标记了开始点
#执行的方式。稍后,“done”伪指令将生成
#程序正常终止。
主要内容:
addi$sp,$sp,-36#保留堆栈空间
#$v0=sprintf(缓冲区,格式,str,255,255,111,-255,-255)

la$a0,buffer#arg 0您需要一个循环来检查
sprintf
函数中的下一个字符。此循环应扫描下一个字符,将其与要使用的可用字符列表进行比较,然后分支到必要的函数,这包括返回循环,以防您得到
%%

,您可以使用C语言获取sprintf实现,并使用MIPS编译器将其机器翻译为MIPS程序集,以便查看它是如何完成的。