assembly ARM 64-计算字符串长度时出现分段错误

lvmkulzt  于 2022-11-13  发布在  其他
关注(0)|答案(1)|浏览(120)

我正在写一个程序,它读入一个字符串,并计算它的长度,以便在程序中使用,这是我目前所拥有的。

ldr x0, =stringread
    ldr x1, =strbuffer //string to be analyzed
    bl scanf

    mov x9, #0 //initialize length = 0
    bl Loop 

Loop:
    ldrb w11, [x1, x9] //load w11 with the x9th value of the string in x1
    cbnz w11, increment_length //until a 0 appears, continue iterating
                               //thru string while incrementing length
    /* what to put here to break the loop once zero is reached?*/

increment_length:
    add x9, x9, #0 
    bl Loop

我不确定如何打破这个循环。我是否应该分支到另一个分支,这个分支只是用来打破这个循环?就像标记为zero_reached的分支一样?我现在遇到了一个分段错误。如果有任何提示或指示,我将不胜感激。
(For参考,这是我的整个程序。它还没有完成,我只需要过去计算长度继续到其他部分)。

.data
outformat:     .asciz "%c"  
flush:          .asciz "\n"      
stringread:     .asciz "%s" 
lengthread:     .asciz "%d" 
strbuffer: .space 100       
lenbuffer: .space 8       

    .text
    .global main

main:       
    ldr x0, =prompt
    mov x1, x0
    bl printf

    ldr x0, =stringread
    ldr x1, =strbuffer
    bl scanf

    mov x9, #0 //length
    bl Loop

Loop:
    ldrb w11, [x1, x9]
    cmp w11, #0
    bne increment_length
    add x9, x9, #1

increment_length:
    add x9, x9, #0 
    bl Loop     

    #Change length to length-1
    sub x0, x0, #1 

    #Move string address to x1
    ldr x1, =strbuffer

    #Starting index for reverse
    mov x2, #0

    #Branch to reverse, setting return address
    bl reverse

    #Flush the stdout buffer
    ldr x0, =flush
    bl printf

    #Exit the program
    b exit

reverse:    #In reverse we want to maintain
            #x0 is length-1
            #x1 is memory location where string is
            #x2 is index

    subs x3, x2, x0

    #If we haven't reached the last index, recurse
    b.lt recurse

base:       #We've reached the end of the string. Print!
    ldr x0, =outformat

    #We need to keep x1 around because that's the string address!
    #Also bl will overwrite return address, so store that too
    stp x30, x1, [sp, #-16]!
    ldrb w1, [x1, x2]
    bl printf
    ldp x30, x1, [sp], #16

    #Go back and start executing at the return
    #address that we stored 
    br x30

recurse:    #First we store the frame pointer(x29) and 
            #link register(x30)
    sub sp, sp, #16
    str x29, [sp, #0]
    str x30, [sp, #8]

    #Move our frame pointer
    add x29, sp, #8

    #Make room for the index on the stack
    sub sp, sp, #16

    #Store it with respect to the frame pointer
    str x2, [x29, #-16]

    add x2, x2, #1 

    #Branch and link to original function. 
    bl reverse

    #Back from other recursion, so load in our index
end_rec:
    ldr x2, [x29, #-16]

    #Print the char!
    stp x30, x1, [sp, #-16]!
    ldr x0, =outformat
    ldrb w1, [x1, x2]
    bl printf
    ldp x30, x1, [sp], #16

    #Clear off stack space used to hold index
    add sp, sp, #16

    #Load in fp and lr
    ldr x29, [sp, #0]
    ldr x30, [sp, #8]

    #Clear off the stack space used to hold fp and lr
    add sp, sp, #16

    #Return to correct location in execution
    br x30

exit:
    mov x0, #0
    mov x8, #93
    svc #0

    .section .data

prompt:
    .asciz "input a string\n"
h9vpoimq

h9vpoimq1#

我不确定你使用的是什么汇编程序,但我可以说你并不总是正确地使用BLBL是“分支with link”,它实际上是一条“call”指令,在分支之前用所需的返回地址覆盖链接寄存器。有时你会正确地使用它(BL printf),有时候不是(BL Loop,当你的意思只是B Loop时)。
另请注意,到'Loop'标签的第一个分支是不必要的,因为它只是到下一条指令的分支,并且您实际上并没有递增长度计数器(您是在给它加0!)。
我对您的循环片段的建议如下:

ldr x0, =stringread
    ldr x1, =strbuffer // String to be analyzed
    bl scanf

    mov x9, #0         // Initialize length = 0

Loop:
    ldrb w11, [x1, x9] // Load w11 with the x9th value of the string in x1
    cbz  w11, LoopEnd  // Until a 0 appears, continue iterating
    add  x9, x9, #1    // Increment x9
    b    Loop
LoopEnd:               // Continue from here

请注意循环分支是无条件的,并且在循环开始附近使用条件分支来转义它。

char * buffer = strbuffer;
int index = 0;
while (buffer[index] != 0) {
    ++index;
}

while循环顶部的条件在每个循环开始时计算,如果不满足,则会导致分支到循环的末尾,就像上面的汇编语言代码一样。

相关问题