我正在学习amd64汇编语言,并尝试实现一个简单的Unix过滤器。出于未知原因,即使将其简化到最基本的版本(如下所示的代码),它也会随机崩溃。
我尝试在GNU调试器(gdb)中调试此程序。在gdb的默认配置下,程序运行正常,但是如果我启用地址随机化(set disable-randomization off
),程序就开始崩溃(SIGSEGV)。问题指令在列表中标记如下:
format ELF64 executable
sys_read = 0
sys_write = 1
sys_exit = 60
entry $
foo:
label .inbuf at rbp - 65536
label .outbuf at .inbuf - 65536
label .endvars at .outbuf
mov rbp, rsp
mov rax, sys_read
mov rdi, 0
lea rsi, [.inbuf]
mov rdx, 65536
syscall
xor ebx, ebx
cmp eax, ebx
jl .read_error
jz .exit
mov r8, rax ; r8 - count of valid bytes in input buffer
xor r9, r9 ; r9 - index of byte in input buffer, that is being processed.
xor r10, r10 ; r10 - index of next free position in output buffer.
.next_byte:
cmp r9, r8
jg .exit
mov al, [.inbuf + r9]
mov [.outbuf + r10], al ;; SIGSEGV here in GDB
inc r10
inc r9
jmp .next_byte
.read_error:
mov rax, sys_exit
mov rdi, 1
syscall
.exit:
mov rax, sys_write
mov rdi, 1
lea rsi, [.outbuf]
mov rdx, r10
syscall
mov rax, sys_exit
xor rdi, rdi
syscall
这个程序旨在从stdin最多读取64kB的数据,将其存储到堆栈上的缓冲区中,逐字节地将读取的数据复制到输出缓冲区中,并将输出缓冲区的内容写入标准输出流中。本质上,它应该像
cat
的限制版本一样运行。在我的电脑上,它要么按预期工作,要么以大约1次成功运行对4次崩溃的频率崩溃。
movzx
的信息。 - KAction