ARM ASM Segfaulting в конце функции - PullRequest
0 голосов
/ 26 апреля 2019

У меня есть следующий код сборки ARM. Цель состоит в том, чтобы распечатать 32-разрядное целое число в шестнадцатеричном символе за символом. Прототипом функции для этой функции сборки является printx(int, int), где первый int - это целое число, которое будет напечатано, а второй - флаг, указывающий, следует ли печатать его в верхнем или нижнем регистре. Переменные данных существуют, когда я сам пытался отладить код, сравнивая вывод printf и вывод моего кода.

.data

derp: .asciz "\nDerp\n"
hex: .asciz "HEX %x\n"
dec: .asciz "\nDEC %d\n"
count: .asciz "\nCOUNT %d\n"

.text

.global printx

printx:
    push {fp, lr}
    mov fp, sp

    mov r11, #1         // firstloop counter "i"
firstloop:              // loop to extract hex character
    cmp r11, #1         // if i == 1
    beq endsecond       // jump to end of loop (no shift necessary)
    lsr r0, r0, #4      // logical shift right 4 bits
endsecond:
    and r4, r0, #0xf    // gets first 4 bits
    cmp r4, #9          // is it greater than 9?
    bgt alpha           // jump to alpha
    add r4, r4, #48     // add 48 to get ascii for number
    b beta              // jump to beta
alpha:
    cmp r1, #1          // if uppercase flag is set
    beq upper           // jump to upper
    add r4, r4, #87     // add 87 to get ascii for lowercase letters
    b beta              // jump to beta
upper:
    add r4, r4, #55     // add 55 to get ascii for uppercase letters
beta:
    push {r4}           // push ascii character onto stack
    cmp r11, #8         // if i == 8
    beq popping         // branch to popping
    add r11, #1         // i++
    b firstloop         // branch to firstloop
popping:
    mov r10, #1          // let r9 indicate leading (1 is true)
poploop:
    pop {r0}            // pop into r5
    cmp r0, #0          // if r5 != 0
    bne nonzero         // branch to nonzero
    cmp r10, #1          // if r10 == 1 (if leading)
    beq counter         // branch to counter
    b print             // branch to print
nonzero:
    mov r10, #0          // set leading (r10) to false (0)
print:
    bl putchar          // call putchar
counter:
    sub r11, #1         // i--
    cmp r11, #0         // if i != 0
    bne poploop         // branch to poploop
    ldr r0, =derp
    bl printf

    mov sp, fp
    pop {fp, pc}
.end

Когда я запускаю gdb, я получаю следующее:

Program received signal SIGSEGV, Segmentation fault.
counter () at printinteger.s:62
62      pop {fp, pc}

Я дважды проверил, что я выталкиваю ровно столько раз, сколько выталкиваю в стек, поэтому я думаю, что это может иметь какое-то отношение к тому, как я выталкиваю указатель кадра и счетчик программы на основе на GDB, или я перемещаю указатель стека в неправильном месте. Буду признателен за любую помощь в диагностике проблемы.

1 Ответ

4 голосов
/ 26 апреля 2019

Вы повредили sp вызывающего абонента, потому что fp и r11 являются синонимами, поэтому ваш mov r11, #1 перезаписывает ваш fp, и вы копируете этот мусор в sp в конце своей функции как результат.

...