assembly 使用堆栈删除字符串中的元音,但我得到的原始字符串中仍有元音

v09wglhw  于 2022-12-04  发布在  其他
关注(0)|答案(1)|浏览(175)

我正在用MIPS编写一些代码,要求用户输入一个字符串,并在Stack的帮助下从该字符串中删除元音,这是我目前所拥有的,抱歉,因为我对MIPS相当陌生,所以有点马虎

.text
    .globl main
    
    
main: 
    li  $v0, 4
    la  $a0, prompt # prompt user for string
    syscall
    
    
    li  $v0, 8      # store string in str buffer
    la  $a0, str
    li  $a1, 120
    syscall
    
    
    
    li  $t4, 0
    li  $t1, 0
    addiu   $sp, $sp, -4    # push a NUL byte onto the stack to signal its bottom
    sw  $zero, ($sp)    # remember, always access the stact using words, not bytes!
    
loop:
    lbu $t0, str($t1)
    nop
    nop
    beqz    $t0, end
    nop
    nop
    addiu   $t1, $t1, 1 #traverse through string until you reach the end of the string
    
    j   loop
    
    
end:

    addiu   $t1, -2     # backing up the index twice to start at the last character of string
    
loop2:  lbu $t0, str($t1)
    nop
    nop
    
    beq $t1, $t4, end2
    nop
    li  $t5, 'a'
    beq $t5, $t0, vowel     # picking up all of the consonants and putting them in the stack
    nop
    li  $t5, 'e'
    beq $t5, $t0, vowel
    nop
    li  $t5, 'i'
    beq $t5, $t0, vowel
    nop
    li  $t5, 'o'
    beq $t5, $t0, vowel
    nop
    li  $t5, 'u'
    beq $t5, $t0, vowel
    nop

    
vowel:  addiu   $t1, $t1, -1        # decrement index of string
    
    addiu   $sp, $sp, -4    # push
    sw  $t0, ($sp)
    nop
    j   loop2
    nop
    nop
end2:
    
    
    
    li  $t1, 0      # index of first byte of str buffer 
popl:   
    lw  $t0, ($sp)  # pop a char off the stack
    addiu   $sp, $sp, 4 # adjust $sp in load delay slot
    beqz    $t0, done   # NUL byte means empty stack
    nop         # branch delay slot
    sw  $t0, str($t1)   # store at string[$t1]
    nop
    addiu   $t1, $t1, 1 # increment the index (in load delay slot)
    j   popl        # loop
    nop         # branch delay slot
                # print the reversed string
done:   li  $v0, 4      # print string service code
    la  $a0, str    # address of string
    syscall
    
    li  $v0, 10     # exit program
    syscall

    
    
    
    
    
    li  $v0, 10
    syscall
    
    
    .data
prompt: .asciiz "enter a word"
number: 

str:    .space   128

我觉得我的很多问题都是关于我如何在堆栈中存储单个字符,以及在打印系统调用之前如何将它们弹出到字符缓冲区中。任何指导都将不胜感激,谢谢

y1aodyip

y1aodyip1#

我认为问题就在这里:

popl:   
    lw  $t0, ($sp)  # pop a char off the stack
    addiu   $sp, $sp, 4 # adjust $sp in load delay slot
    beqz    $t0, done   # NUL byte means empty stack
    nop         # branch delay slot
    sw  $t0, str($t1)   # store at string[$t1]
    nop
    addiu   $t1, $t1, 1 # increment the index (in load delay slot)
    j   popl        # loop
    nop         # branch delay slot

看到sw $t0, str($t1)这行了吗?应该是sb $t0,str($t1)。因为堆栈需要始终保持字对齐,所以必须将所需的字母作为32位字存储在堆栈中。但是,字符串 * 中的每个字符 * 只占用一个字节,所以需要使用sb将它们存储到字符串中。
作为一个例子,我将展示如果使用输入字符串“BOOBOO”运行代码会发生什么。
这表示第一次通过时发生的情况:

popl:   
    lw  $t0, ($sp)        # $t0 = 0x00000042 (0x42 in ASCII = 'B')
    addiu   $sp, $sp, 4   # adjust $sp in load delay slot
    beqz    $t0, done     # NUL byte means empty stack
    nop                   # branch delay slot
    sw  $t0, str($t1)     # store at string[$t1]
    nop                   # load delay slot

在商店之后,我们有以下内容:

str:
.word 0x00000042 #could be 0x42000000 depending on your CPU's endianness
.space 124

在存储之后,我们执行以下命令并再次循环:

addiu   $t1, $t1, 1 # increment the index (in load delay slot)
    j   popl            # loop
    nop                 # branch delay slot

如果您使用的是sb $t0, str($t1)addiu $t1,$t1,1就不会有问题。但是,由于您使用的是sw,您会得到一个错误。这是因为MIPS * 中的lwsw只能用于字对齐的地址,* 即它们的十六进制值以0、4、8、否则将导致对齐错误。执行addiu $t1, $t1, 1.时,语句sw $t0, str($t1)变为未对齐

  • 旁注:像这里这样使用标签作为常量偏移量并不是一个好的做法。原因是,如果在它们上面存储一个字符串,它们可能会导致类似的对齐错误,如下所示:*
foo: .asciiz "Hello"  #total of 6 bytes, so the array below is unaligned
bar: .space 128       #doing "sw $t1,bar($t0) would cause an alignment fault if $t0 = 0.

相关问题