GAS Assembler — функция Fgets SegFaults

Эта простая программа дает сбой, когда я пытаюсь использовать fgets. Вместо этого я попытался использовать функцию чтения с

       ldr r1, =input_string
       mov r3, #80
       mov r0, #0
       bl read

но это не с

read(0, 0x21044, 3201061676) = -1 EINVAL (неверный аргумент)

Поэтому я пытаюсь использовать fgets. Кажется, что-то не так с моим строковым буфером?

.data

.balign 4
message1:       .asciz "Please type a string: \n"

.balign 4
input_string:
        .asciz ""
        .zero 80

return: .word 0

.text
.global main

main:
        push {lr}
        ldr r0, =message1
        bl printf
        mov r0, #0
        bl fflush

        ldr r0, =input_string
        mov r1, #80
        mov r2, #0

        bl fgets

        mov r0, r1
        bl printf

        pop {lr}
        bx lr
.end


.global printf
.global read
.global fgets

РЕДАКТИРОВАТЬ: я попытался использовать стандартный ввод в соответствии с примером, приведенным в комментариях, но это не удалось скомпилировать, говоря: Ошибка: для немедленного выражения требуется префикс # -- `mov r2,=stdin'

    ldr r0, =input_string
    mov r1,   #80
    mov r2,   =stdin
    ldr r2,   [r2]

Кажется, нет предопределенного макроса для стандартного ввода, как в C, так как мне сказать ему использовать стандартный ввод?


person Rick Dearman    schedule 29.09.2020    source источник
comment
Что вы ожидаете, когда вы передаете указатель NULL для FILE* 3-го аргумента fgets? man7.org/linux/man-pages/man3/fgets.3. html read принимает дескриптор файла Unix (в качестве первого аргумента), fgets принимает stdio FILE* в качестве последнего аргумента.   -  person Peter Cordes    schedule 29.09.2020
comment
Подсчет символов в строке в armV7 показывает, как использовать fgets.   -  person Peter Cordes    schedule 29.09.2020
comment
Только что заметил, что ваш вызов read передает длину в r3, несуществующем 4-м аргументе, а не в r2 (3-й аргумент). Кроме того, в ассемблере довольно часто встраивается инструкция системного вызова svc вместо вызова оболочки libc. (С номером вызова в R7, IIRC). Но вам не нужно этого делать.   -  person Peter Cordes    schedule 29.09.2020
comment
Я передал строковый буфер как arg1, количество байтов как arg2 и то, что я думал, было стандартным вводом, но пример, на который вы ссылаетесь, похоже, показывает предопределенный стандартный ввод. Но когда я пытаюсь это не работает. ldr r0, =input_string mov r1, #80 mov r2, =stdin ldr r2, [r2]   -  person Rick Dearman    schedule 29.09.2020
comment
Да, FILE *stdin — это глобальная переменная-указатель, инициализированная стартовым кодом libc для указания на структуру FILE. Я ожидал, что это сработает, по крайней мере, если вы сделаете ldr r2, =stdin, а не mov. Посмотрите на вывод компилятора C (godbolt.org)   -  person Peter Cordes    schedule 29.09.2020
comment
Спасибо! Я понял, что использовал неправильную инструкцию (mov вместо ldr), как раз перед тем, как посмотрел ваш комментарий. Спасибо за помощь.   -  person Rick Dearman    schedule 29.09.2020


Ответы (1)


   ldr r0,=input_string
   mov r1,#80
   ldr r2,=stdin
   ldr r2,[r2]
   bl fgets

Ответ заключается в использовании LDR и стандартного ввода.

person Rick Dearman    schedule 29.09.2020