在汇编中,我的函数试图返回值是否有问题?

时间:2014-10-10 03:32:41

标签: assembly

在汇编中,'pop'命令用于返回指定的值吗?我似乎无法让它正常工作。我尝试打印输入以查看输入是否已更改,但程序改为循环两次,然后再次等待用户输入。

数据声明:

 section .data
  test db "Test",10
  testLen equ $-test

这是输入声明

section .bss
 input resb 1   

然后子程序调用:

section .text
 global _start

 _start:

 sub esp,2    ;this is for the return value
 call function    ; call the subprogram
 pop word[input]

 mov eax,4
 mov ebx,1
 mov ecx,input
 mov edx,1 ;1 character input only from user is expected
 int 80h

 mov eax,4
 mov ebx,1
 mov ecx,test
 mov edx,testLen
 int 80h

 jmp _start

然后子程序:

function:
 mov eax,3
 mov ebx,0
 mov ecx,[esp+4]
 mov edx,2 ;of length 2 because only 1 character is expected from user + the \n char 
 int 80h

 ret

我在子程序'功能'中的扫描程序出错了吗?谢谢那些能帮助我的人。刚刚开始学习大会的子程序,我无法想出这个。被困在这个简单的bug一小时了。

2 个答案:

答案 0 :(得分:0)

好的,让我看看我是否猜测你在哪里误解并帮助你清理它。

你听过一个由知识分子吹嘘的短语,它就像这样“堆栈用于在函数之间传递变量。”是的,这是真的;但不完全正确,它让你的生活日光混乱。

我还假设您正在考虑C和汇编语境。

现在好了,就C来说,一个函数有一个“类型”,正如我猜你知道的那样。

关于汇编语言,函数没有类型。

(我们会在这里坚持使用x86,尽管它通常适用于其他一些人)

对于汇编语言,您有调用指令和 Ret 指令,就是它。

哦,是的,你在x86上有 Int 指令,还有一些其他类似的芯片;但就目前而言,我们只关注致电 Ret

所以无论如何,这个“在堆栈上传递参数”的商业是(至少在C中)大致总是设置为

  • 参数传递 TO 堆栈上的函数
  • 值返回 FROM 寄存器中的函数

我认为这就是你的困惑所在。

我可以看到你对学习装配的渴望是认真的,并且你在使用堆栈传递变量方面是“创造性的”。

谁知道?也许你已经注意到了一种更好的方式(但我很怀疑它;使用寄存器来做你想做的事情)

无论如何,如果我正确猜测,你永远不会在你为function填充的堆栈中的那个空间写任何东西

以下是您要确认或否认的事项。

通过单步执行调试,在这三条指令的每一条中使用断点...

  sub    esp,2        ;this is for the return value
  call   function     ; call the subprogram
  pop    word[input]

打开观察窗口,观察call function指令之前和之后[Esp]的记忆位置。

我想你会发现你从未在那个地方写过任何东西。

然而,虽然这个概念可能适用于这种情况,但尝试通常是一个不太好的想法;所以要节省很多麻烦,并在寄存器中返回一个值。

编译器就是这样做的;并且问新专家:编译器比人类聪明(但我离题了)

不确定这是否有帮助,但我尝试过。

答案 1 :(得分:0)

返回值通常在eax中返回,并且只有参数和局部变量存储在堆栈中,但这在调用约定之间会有所不同。

例如,在C语言中使用的cdecl调用约定如下所示:

int callee(int, int, int);

int caller(void)
{
    int ret;
    ret = callee(1, 2, 3);
    ret += 5;
    return ret;
}

转换为:

caller:
    push    ebp      ; store previous stack frame
    mov     ebp, esp ; set current stack frame (could be used to access local variables and arguments)
    push    3        ; push arguments to stack from right to left
    push    2
    push    1
    call    callee   ; eax contains return value of callee after this line
    add     esp, 12  ; clean stack from arguments passed to callee
    add     eax, 5   ; add 5 return value of callee
    pop     ebp      ; restore previous stack frame
    ret              ; return value in eax

维基百科有很多关于不同调用约定的文章(http://en.wikipedia.org/wiki/X86_calling_conventions)。