【发布时间】:2023-01-01 18:46:15
【问题描述】:
我编写了一个 x86 (IA-32) 汇编程序,它应该从标准输入中读取一个字符串,但无法理解为什么它会导致 SEGFAULT。
我用 GNU 汇编器组装了这个程序 使用以下标志:
$ gcc (flags used) (file_name)
下面是程序的代码:
.text
.globl _start
MAX_CHAR=30
_start:
## Start message ##
movl $4, %eax
movl $1, %ebx
movl $msg, %ecx
movl $len, %edx
int $0x80
## READ ##
movl $3, %eax #sys_read (number 3)
movl $0, %ebx #stdin (number 0)
movl %esp, %ecx #starting point
movl $MAX_CHAR, %edx #max input
int $0x80 #call
## Need the cycle to count input length ##
movl $1, %ecx #counter
end_input:
xor %ebx, %ebx
mov (%esp), %ebx
add $1, %esp #get next char to compare
add $1, %ecx #counter+=1
cmp $0xa, %ebx #compare with "\n"
jne end_input #if not, continue
## WRITE ##
sub %ecx, %esp #start from the first input char
movl $4, %eax #sys_write (number 4)
movl $1, %ebx #stdout (number 1)
movl %ecx, %edx #start pointer
movl %esp, %ecx #length
int $0x80 #call
## EXIT ##
movl $1, %eax
int $0x80
.data
msg: .ascii "Insert an input:\n"
len =.-msg
是什么导致了 SEGFAULT?
欢迎任何帮助。
【问题讨论】:
-
请注意,将来有关汇编语言的问题应始终标记为assembly,以及您正在为其编码的体系结构(此处为x86)。 gnu-assembler 用于特定于 GNU 汇编器的东西,它可以针对许多不同的体系结构。
-
另外请具体说明您面临的问题。仅仅说代码“错误”是非常无用的。你是怎么运行的?用什么输入?它做了什么?你期望它做什么?
-
抱歉,这是 x86 Linux 计算机 5.15.0-52-generic #58-Ubuntu SMP Thu Oct 13 08:03:55 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
-
movl %esp, %ecx:这将覆盖堆栈的当前内容,这是不好的;堆栈甚至可能不足以容纳您的输入数据,这会更糟。您需要减少堆栈指针以为您的缓冲区腾出空间。类似于subl $MAX_CHAR, %esp,除了堆栈应至少保持 4 个字节对齐,所以subl $32, %esp。然后在完成缓冲区后添加 32。 -
mov (%esp), %ebx加载一个 32 位字(4 个字节),而您实际上只想比较一个字节。所以使用 8 位寄存器,例如mov (%reg), %bl然后是cmp $0xa, %bl。或者只是将它们组合在一起并完全跳过寄存器加载:cmpb $0xa, (%reg)。
标签: assembly x86 segmentation-fault