ARM64 - Ошибка сегментации при расчете длины строки - PullRequest
0 голосов
/ 20 октября 2018

Я пытаюсь написать программу, которая читает строку и вычисляет ее длину для последующего использования в программе.Это то, что я до сих пор.

    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?Я сейчас получаю ошибку сегментации.Любые советы или указатели будут высоко оценены.

(Для справки, это вся моя программа. Она еще не завершена, и мне просто нужно пройти расчет длины, чтобы перейти к другим частям).

    .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"

1 Ответ

0 голосов
/ 20 октября 2018

Я не уверен, какой ассемблер вы используете, но могу сказать, что вы не всегда правильно используете BL.BL - это «ветвь со ссылкой», которая фактически является инструкцией «вызова» и перед ветвлением перезаписывает регистр связи требуемым обратным адресом.Иногда вы используете это правильно (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

Обратите внимание, что ветвление цикла является безусловным, и условная ветвь используется около начала цикла для его выхода.Это примерно то, что сгенерирует компилятор C, если представить его с кодом, подобным

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

Условие в верхней части цикла while оценивается в начале каждого цикла и вызывает переход к концуцикла, если он не выполняется, как в приведенном выше коде на ассемблере.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...