GAS Assembler - ฟังก์ชัน Fgets SegFaults

โปรแกรมง่ายๆ นี้ segfaults เมื่อฉันพยายามใช้ fgets ฉันได้ลองใช้ฟังก์ชั่นการอ่านแทนด้วย

       ldr r1, =input_string
       mov r3, #80
       mov r0, #0
       bl 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

แก้ไข: ฉันพยายามใช้ stdin ตามตัวอย่างที่ให้ไว้ในความคิดเห็น แต่ไม่สามารถคอมไพล์ได้โดยบอกว่า: ข้อผิดพลาด: การแสดงออกทันทีต้องใช้คำนำหน้า # -- `mov r2,=stdin'

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

ดูเหมือนจะไม่มีมาโครที่กำหนดไว้ล่วงหน้าสำหรับ stdin เหมือนใน C ดังนั้นฉันจะบอกให้มันใช้ stdin ได้อย่างไร


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 ซึ่งเป็น arg ที่ 4 ที่ไม่มีอยู่จริง แทนที่จะเป็น r2 (arg ที่ 3) นอกจากนี้ ใน asm เป็นเรื่องปกติที่จะอินไลน์คำสั่ง svc system-call แทนที่จะเรียก libc wrapper (โดยมีหมายเลขโทรศัพท์อยู่ใน R7, IIRC) แต่คุณไม่จำเป็นต้องทำอย่างนั้น   -  person Peter Cordes    schedule 29.09.2020
comment
ฉันส่งบัฟเฟอร์สตริงเป็น arg1 จำนวนการกัดเป็น arg2 และสิ่งที่ฉันคิดว่าเป็น stdin แต่ตัวอย่างที่คุณเชื่อมโยงไปดูเหมือนว่าจะแสดง stdin ที่กำหนดไว้ล่วงหน้า แต่เมื่อฉันลองมันก็ไม่ได้ผล 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 และ stdin

person Rick Dearman    schedule 29.09.2020