linux x86汇编语言sys_read调用的第一个参数应为0(stdin)

linux x86汇编语言sys_read调用的第一个参数应为0(stdin),linux,assembly,x86,file-descriptor,Linux,Assembly,X86,File Descriptor,我当时正在编写一个简单的汇编程序来读取stdin(比如scanf)。 这是我的密码 section .bss num resb 5 section .txt global _start _start: mov eax,3 ;sys_read mov ebx,0 ;fd 0 mov ecx,num mov edx,5 int 0x80 mov eax,4 ;sys_write mov ebx,1 ;fd 1 mov ecx,num mov edx,5 int 0x80

我当时正在编写一个简单的汇编程序来读取stdin(比如scanf)。 这是我的密码


section .bss
num resb 5

section .txt
global _start

_start:

mov eax,3   ;sys_read
mov ebx,0   ;fd 0
mov ecx,num
mov edx,5
int 0x80

mov eax,4   ;sys_write
mov ebx,1   ;fd 1
mov ecx,num
mov edx,5
int 0x80

mov eax,1   ;sys_exit
mov ebx,0   ;return 0
int 0x80
现在它正常工作了,可以读取和打印

所以,我尝试将sys_read调用中的文件描述符值更改为1(stdout),2(syserr)

代码

此代码也可以正常工作。
我的问题是,即使在将文件描述符从0更改为1之后,为什么该代码仍能正常工作。
sys_read应该将0作为fd。

当您测试它时,您正在运行程序,并且stdin、stdout和stderr都连接到您的终端。碰巧所有3个文件描述符所引用的文件描述都是读/写的

FD0并没有什么神奇之处可以阻止文件描述符的读/写

我认为shell可以分别为只读和写操作打开终端,而不是运行所有3个标准文件描述符都是相同读写文件描述副本的程序。(设置为)。但bash(或启动bash的终端仿真器)并不是这样设计的


试着运行你的
sys\u read(1,…)
版本,其中stdin是一个管道或文件,它肯定只为读取而打开,而stdout是一个只为写入而打开的fd

$ echo foo | strace ./read1 > foo.out
execve("./read1", ["./read1"], 0x7fff68953560 /* 52 vars */) = 0
strace: [ Process PID=31555 runs in 32 bit mode. ]
read(1, 0x80490ac, 5)                   = -1 EBADF (Bad file descriptor)
write(1, "\0\0\0\0\0", 5)               = 5
exit(0)                                 = ?
+++ exited with 0 +++
因此
read(1,num,5)
返回了
-EBADF
(错误的文件描述符),因为fd1是一个只写fd,在这个进程的fork/execve之前由shell打开<代码>写入(1,…)仍然发生,因为您的程序没有执行任何错误检查。(这很好;我们有像
strace
这样的工具,所以我们在尝试系统调用时会很懒)


但是请注意,重定向stdin没有任何区别;你的程序从不使用FD0

当fd 1连接到tty时,无论输入重定向如何,从其读取都从终端读取

$ echo test | strace ./read1
execve("./read1", ["./read1"], 0x7ffc3c42d620 /* 52 vars */) = 0
strace: [ Process PID=31462 runs in 32 bit mode. ]
read(1,                                   # it blocked here until I pressed return
"\n", 5)                        = 1
write(1, "\n\0\0\0\0", 5
)               = 5
exit(0)                                 = ?
+++ exited with 0 +++
在另一个终端中,
read1
暂停等待
read()
返回时:

$ ll /proc/$(pidof read1)/fd 
total 0
lr-x------ 1 peter peter 64 Feb 22 18:17 0 -> pipe:[13443590]
lrwx------ 1 peter peter 64 Feb 22 18:17 1 -> /dev/pts/17
lrwx------ 1 peter peter 64 Feb 22 18:17 2 -> /dev/pts/17
lrwx------ 1 peter peter 64 Feb 22 18:17 49 -> socket:[405352]
lrwx------ 1 peter peter 64 Feb 22 18:17 53 -> socket:[405353]

注意fd 1上的RWX:该符号链接上的权限反映了它是读、写还是读+写fd。

对于该问题的回答非常准确。谢谢
$ ll /proc/$(pidof read1)/fd 
total 0
lr-x------ 1 peter peter 64 Feb 22 18:17 0 -> pipe:[13443590]
lrwx------ 1 peter peter 64 Feb 22 18:17 1 -> /dev/pts/17
lrwx------ 1 peter peter 64 Feb 22 18:17 2 -> /dev/pts/17
lrwx------ 1 peter peter 64 Feb 22 18:17 49 -> socket:[405352]
lrwx------ 1 peter peter 64 Feb 22 18:17 53 -> socket:[405353]