кронштейн для сборки мусора только на струнах длиной 12 - PullRequest
0 голосов
/ 22 ноября 2018

Я столкнулся со странной проблемой при кодировании связанного списка в сборке руки на Raspberry Pi.Мой связанный список работает для всех строк, кроме строк длиной 12. Он отображает символ мусора в конце всех строк длиной 12, и я не могу понять, почему

любая помощь приветствуется

вот входная функция, которую я использую, она выводит адрес строки malloc в R0 и, кажется, работает правильно для всех строк не длиной 12:

.equ    BUFSIZE2,256

.data
inputbuf2:  .ds BUFSIZE2
prompt:     .asciz  "Enter: "
p1:     .word   0

input:
    push {R1,R2,R5,R14}
    mov R0,#0
    bl  v_ascz        @ prints string in R1
    ldr R1,=inputbuf2
    mov R2,#BUFSIZE2
    bl  c_ascz        @ does service call for input, returns in R1
    bl  v_ascz
    bl  v_nl
    bl  strlen        @ returns string length of R1 into R0
    sub R0,#1
    mov R5,R0
    bl  alloc
    bl  store
    ldr R0,=p1
    ldr R0,[R0]
    pop {R1,R2,R5,R14}
    bx  LR

alloc:
    push {R0-R4,R14}
    bl  malloc
    ldr R1,=p1
    str R0,[R1]
    pop {R0-R4,R14}
    bx  LR

store:
    push    {R1-R4,R14}
    mov R2,#0       @ index
    ldr R4,=p1
    ldr R4,[R4]
    loop:   ldrb    R3,[R1],#1
    strb    R3,[R4],#1
    add R2,#1
    cmp R2,R5
    blt loop

    mov R3,#0
    strb    R3,[R4]       @ store null at end of string
    pop {R1-R4,R14}
    bx  LR


.end

А вот и связаннаясписок добавить функцию узла, который я использую.Он распределяет 8 байтов и сохраняет адрес для данных в первых четырех и адрес для следующего узла в последних 4:

.global list_add
@   R1  =   addr of head
@   R2  =   addr of tail
@   R3  =   data
.data
node:   .word   0

list_add:
    push    {R1-R4,R14}
    bl  alloc
    push    {R2}
    ldr R2,[R2]
    cmp R2,#0
    pop {R2}
    beq first_node
            @ normal add
    ldr R4,=node
    ldr R4,[R4]
    push    {R2}
    ldr R2,[R2]     @ R2 = tail node
    str R4,[R2,#4]  @ R2 next ptr = node
    pop {R2}
    str R4,[R2]     @ tail = node
    str R3,[R4]     @ node data = first addr of data
    mov R3,#0
    str R3,[R4,#4]
    pop {R1-R4,R14}
    bx  LR

first_node:
    push    {R1-R4}
    ldr R4,=node
    ldr R4,[R4]
    str R4,[R1]     @ head = node
    str R4,[R2]     @ tail = node
    str R3,[R4]     @ node data = data
    mov R3,#0
    str R3,[R4,#4]
    pop {R1-R4}
    pop {R1-R4,R14}
    bx  LR

alloc:
    push    {R1-R3,R14}
    mov R0,#8
    bl  malloc
    ldr R1,=node
    str R0,[R1]
    ldr R1,[R1]
    mov R3,#0
    str R3,[R1]
    str R3,[R1,#4]
    pop {R1-R3,R14}
    bx  LR

Добавляя несколько случайных строк, извивающихся вокруг собаки моей подруги,это выход .игнорируйте числа, это десятичные адреса памяти malloc'd

1 Ответ

0 голосов
/ 22 ноября 2018

Строки, как правило, заканчиваются нулевым байтом, называемым «символом завершения».

Когда вы вызываете strlen, вы получаете количество символов в строке, исключая символ завершения, который отмечает ееконец.Это вызывает две проблемы:

  • Когда вы циклически копируете строку, вы не копируете символ завершения.Поэтому ваша строка будет заканчиваться следующим байтом в памяти, который оказывается нулем, который может быть где угодно.Вы видите результат неопределенного поведения: нет причины, по которой 12 символов не должны работать, когда другие цифры работают, это просто следствие ваших конкретных обстоятельств.
  • Если вы добавите символ завершения, вы 'я буду переполнять ваш целевой строковый буфер, потому что ваш вызов malloc также не выделяет достаточно места для символа завершения.

Пока я здесь, я мог бы также отослать вас кARM ABI, а именно часть о стандарте вызова процедур .Хотя ABI не исключает использование r0-r3 для промежуточных значений, эти регистры (наряду с r12) являются "замкнутыми" при вызове, поэтому обычно используется r4-r11 для промежуточных вычислений.Функции должны сохранять r4-r11, обычно с использованием стека.Поэтому использование r5 для хранения аргумента функции (до store) противоречит ABI, поэтому ваша функция store не будет вызываться из кода, совместимого с ABI;и ваше нажатие r1-r3 в нескольких местах не требуется, если ваши абоненты также соответствуют ABI.Также следует отметить, что для ABI требуется выравнивание стека по 8 байт между вызовами функций в разных единицах перевода, поэтому для сохранения этой привычки полезно иметь привычку вставлять и выталкивать четные числа регистров.(Если вы вызываете библиотечную функцию типа malloc или strlen без обеспечения, например, 8-байтового выравнивания, вы можете снова столкнуться с неопределенным поведением.)

...