Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux gdb不接受输入重定向_Linux_Assembly_X86_Gdb_Debian - Fatal编程技术网

Linux gdb不接受输入重定向

Linux gdb不接受输入重定向,linux,assembly,x86,gdb,debian,Linux,Assembly,X86,Gdb,Debian,我在Debian Linux(Jessie/Testing)中无法完全理解gdb的问题。当试图调试汇编程序时,我无法让gdb接受输入重定向。以下是我试图调试的代码: #The program reverses the input given to it. For example "123456789" will #become "987654321" .global _start readme: pushw $0 #allocate 2 bytes onto t

我在Debian Linux(Jessie/Testing)中无法完全理解
gdb
的问题。当试图调试汇编程序时,我无法让
gdb
接受输入重定向。以下是我试图调试的代码:

#The program reverses the input given to it.  For example "123456789" will 
#become "987654321"

.global _start

readme:
    pushw $0          #allocate 2 bytes onto the stack
    movl $3,%eax      #system call for read
    movl $0,%ebx      #stdin
    movl %esp,%ecx    #read to stack pointer
    movl $1,%edx      #number of bytes to read
    int  $0x80        #execute instruction

    cmpl $0,%eax      #check number of bytes read
    jz  returnme      #jump to label 'returnme' if zero bytes are read

writeme:
    call readme       #recursive call to continue to next character

    movl $4,%eax      #system call for write
    movl $1,%ebx      #stdout
    movl %esp,%ecx    #write what is in the stack pointer
    movl $1,%edx      #write one byte
    int  $0x80        #execute instruction

returnme:
    popw %ax          #clean up
    ret               #return to line after previous call

_start:
    call readme       #call subroutine readme

endit:
    movl $1,%eax      #These lines are for exiting the program
    movl $0,%ebx
    int  $0x80
我使用以下命令编译它:

as -gstabs -o foo.o foo.s
ld -o foo foo.o
as --32 -gstabs foo.s -o foo.o 
ld -m elf_i386 foo.o -o -foo
然后我像这样运行gdb:

gdb foo
(gdb) r <test.in 1>test1.out
+-----------+
|      0    |
+-----------+
| endit-hi  |
+-----------+
| endit-lo  |
+-----------+
+-----------+
| write2-hi |
+-----------+
| write2-lo |
+-----------+
|      0    |
+-----------+
| endit-hi  |
+-----------+
| endit-lo  |
+-----------+
gdbfoo
(gdb)r test1.out

当我在安装了GDB7.6.2的Debian Jessie笔记本电脑上运行这个程序时,它会出现故障。但是,当我在DebianLinux服务器上运行此代码时(运行sid,same
gdb
version),代码会执行它应该执行的操作。我已经把它交上来了,但我很好奇为什么我的笔记本电脑会出故障。有什么想法吗?

您使用的
pushw
/
popw
使堆栈指针错位,这样做不好。我的猜测是,您笔记本电脑上的某些组件(可能是系统调用时的内核本身)不喜欢这样,并导致了故障


顺便问一下,在你的笔记本电脑上,代码在gdb之外运行正常吗?

首先,在代码中没有注释,也没有解释程序应该做什么,这不是一个好的提问方式。但是,由于您在这里相对较新,我将通过发布代码的注释版本来帮助您:

.global _start

readme:
    pushw $0
    movl $3,%eax        ; sys_read
    movl $0,%ebx        ; file = stdin
    movl %esp,%ecx      ; pointer to userbuff
    movl $1,%edx        ; count = 1
    int  $0x80          ; do it

    cmpl $0,%eax        ; check return value
    jz  returnme        ; if it's zero, return

writeme:
    call readme         ; dangerous recursion!
write2:
    movl $4,%eax        ; sys_write
    movl $1,%ebx        ; file = stdout
    movl %esp,%ecx      ; pointer to userbuff = stack?!
    movl $1,%edx        ; 1 byte
    int  $0x80          ; do it

returnme:
    popw %ax            ; clean up stack
    ret                 ; return 

_start:
    call readme

endit:
    movl $1,%eax        ; sys_exit
    movl $0,%ebx        ; error code = 0 (OK)
    int  $0x80          ; do it
因此,代码似乎试图做的是从输入复制到输出。问题出在我评论为“危险递归”的那一行中。当代码第一次从
start
开始时,它推送子程序的返回地址,即
endit
的32位地址。然后在
readme
的顶部推送16位值0。渲染为16位值时,堆栈如下所示:

gdb foo
(gdb) r <test.in 1>test1.out
+-----------+
|      0    |
+-----------+
| endit-hi  |
+-----------+
| endit-lo  |
+-----------+
+-----------+
| write2-hi |
+-----------+
| write2-lo |
+-----------+
|      0    |
+-----------+
| endit-hi  |
+-----------+
| endit-lo  |
+-----------+
如果sys_read调用返回的不是零(它每次成功读取字符时都会返回零),那么我们将递归调用
readme
。堆栈现在如下所示:

gdb foo
(gdb) r <test.in 1>test1.out
+-----------+
|      0    |
+-----------+
| endit-hi  |
+-----------+
| endit-lo  |
+-----------+
+-----------+
| write2-hi |
+-----------+
| write2-lo |
+-----------+
|      0    |
+-----------+
| endit-hi  |
+-----------+
| endit-lo  |
+-----------+
然后我们再按一个0字,得到如下结果:

+-----------+
|      0    |
+-----------+
| write2-hi |
+-----------+
| write2-lo |
+-----------+
|      0    |
+-----------+
| endit-hi  |
+-----------+
| endit-lo  |
+-----------+

基本上,每次从
stdin
读取字符时,它都会替换堆栈上最新的
0
,但会很快消耗大量堆栈空间-每个输入字符三个16位字。如果读取大文件,这很可能会导致堆栈崩溃。

我通常不会回答自己的问题,但我找到了它不起作用的原因。当使用64位操作系统时,as和ld应该知道您何时尝试编译和链接32位文件。出于某种原因,这在过去一直运作良好。然而,有了这个项目,情况却并非如此(我认为我过去只是幸运而已)。无论如何,对上述命令的更正如下:

as -gstabs -o foo.o foo.s
ld -o foo foo.o
as --32 -gstabs foo.s -o foo.o 
ld -m elf_i386 foo.o -o -foo

是程序正常工作所必需的。特别是当我试图编译64位操作系统下的汇编代码并将其链接到32位可执行文件时。

我认为这是因为我使用的是pushw而不是pushl(popw也是如此)?代码根本不在gdb之外运行。我想我知道了为什么(或者至少在我的系统上为什么)它不工作了。试图在64位操作系统上编译32位程序集无效。我在代码中添加了注释。很抱歉,我完全忘记了告诉代码的作用和注释。我太专注于问题本身了。现在有了这个项目的实际目的,也许更容易理解我为什么这样做。