2016-10-17 99 views
0

我必须在汇编中做一个非常简单的任务:从用户(名称)读取输入,然后输出这个输入。函数gets()汇编

我必须这么做的方法 - 使用函数gets()。我知道这个函数不应该被使用,但是老师指定任务只使用gets函数。

我面对的问题 - 每当我调用这个函数并输入我的输入时,它会给我出现分段错误。举例来说,我使缓冲区大小等于24个字节。

不管我在堆栈上给这个函数多少内存 - 总是出现同样的错误。一个有趣的事情:如果我leaq -(k*24)(%rsp), %rsp然后mov %rsp, %rdi,然后打电话gets将允许我输入尽可能多的输入,我想要的,永不停止。它只发生在你想要的24号和任何k

为什么会发生?

谢谢。

功能name

.string1: 
     .string "Please enter your name: " 
.string2: 
     .string "Hello, %s" 


.globl name 

name: 
    push %rbx 
    push %rbp    #calee saved regs 

    leaq -24(%rsp),%rsp   # name_str[24] 
    mov %rsp, %rbp    #save rsp 

    movq $.string1, %rdi 
    xorl %eax,%eax 
    call printf 

    movq %rsp, %rdi 
    call gets 
    movq $.string2, %rdi 
    mov %rax, %rsi 
    xorl %eax, %eax 
    call printf 
    ret 

UPDATE1:对不起,我早不提:我主要写C,它只是简单地调用该函数:

 #include <stdlib.h> 
    void name(void); 
    void main() 
    { 
     name(); 
     return; 
    } 

UPDATE2:我使用Linux 64bitGCC 4.8.4(相当老,我知道)

更新3:使用gcc -o exec main.c name.s来链接。

+0

[为什么这样得到的功能太危险了,应该不要使用](http://stackoverflow.com/questions/1694036/why-is-the-gets - 功能那么危险的 - 也就是说,它 - 应该 - 不被使用的)。 **编辑** ....所以,改变你的老师/学校 – LPs

+1

@LPs如果我有足够的钱,我会做半年前:) – beervoley

+0

你确定代码崩溃'gets'?因为当你尝试“ret”到错误的地址时肯定会崩溃(在你返回之前你必须弹出所有的东西!)。 – fuz

回答

0

我所做的更改已经向您指出,但由于您有90%的改动,我认为我会为您修复它。可能会有关于ENTER的评论,但重点是,我们正在做一些工作,而不是担心优化。

您的版本也不会链接,因为GCC预计main作为入口点,除非您将-e name传递给链接器。

.string1: 
     .string "Please enter your name: " 
.string2: 
     .string "Hello, %s\n" 


.globl main 

main: 
     enter $80, $0 

     movl $.string1, %edi 
     call printf 

     movq %rsp, %rdi 
     call gets 

     movl $.string2, %edi 
     mov  %rax, %rsi 
     call printf 

     leave 
     xorl %eax, %eax 
     ret 
+0

是的,它的工作原理,谢谢。 问题在于ret。 – beervoley

0

在增加堆栈大小之前,您不应该将rsp保存到rbp中吗?还应该在离开tge函数之前清理rsp和rbp吗?