【发布时间】:2020-09-29 06:56:31
【问题描述】:
当我尝试使用 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
编辑: 我尝试按照 cmets 中给出的示例使用标准输入,但这无法编译说: 错误:立即表达式需要 # 前缀 -- `mov r2,=stdin'
ldr r0, =input_string mov r1, #80 mov r2, =stdin ldr r2, [r2]
似乎没有像 C 中那样为“stdin”预定义的宏,那么我如何告诉它使用 stdin?
【问题讨论】:
-
当您为
FILE*的fgets的第三个参数传递NULL指针时,您期望什么? man7.org/linux/man-pages/man3/fgets.3.htmlread采用 Unix 文件描述符(作为第一个 arg),fgets采用 stdioFILE*作为最后一个 arg。 -
Counting Characters in a String in armV7 展示了如何使用
fgets。 -
刚刚注意到您的
read调用传递了r3中的长度,这是一个不存在的第四个参数,而不是r2(第三个参数)。此外,在 asm 中,内联svc系统调用指令而不是调用 libc 包装器是相当常见的。 (使用 R7,IIRC 中的索书号)。但你不需要这样做。 -
我将字符串缓冲区传递为 arg1,将字节数传递为 arg2,并且我认为是标准输入,但您链接到的示例似乎显示了预定义的标准输入。但是当我尝试它时它不起作用。 ldr r0, =input_string mov r1, #80 mov r2, =stdin ldr r2, [r2]
-
是的,
FILE *stdin是一个全局指针变量,由 libc 启动代码初始化以指向FILE结构。我本以为它会起作用,至少如果你做了ldr r2, =stdin而不是mov。查看 C 编译器输出 (godbolt.org)
标签: assembly arm fgets gnu-assembler