在汇编中,'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一小时了。
答案 0 :(得分:0)
好的,让我看看我是否猜测你在哪里误解并帮助你清理它。
你听过一个由知识分子吹嘘的短语,它就像这样“堆栈用于在函数之间传递变量。”是的,这是真的;但不完全正确,它让你的生活日光混乱。
我还假设您正在考虑C和汇编语境。
现在好了,就C来说,一个函数有一个“类型”,正如我猜你知道的那样。
关于汇编语言,函数没有类型。
(我们会在这里坚持使用x86,尽管它通常适用于其他一些人)
对于汇编语言,您有调用指令和 Ret 指令,就是它。
哦,是的,你在x86上有 Int 指令,还有一些其他类似的芯片;但就目前而言,我们只关注致电和 Ret 。
所以无论如何,这个“在堆栈上传递参数”的商业是(至少在C中)大致总是设置为
我认为这就是你的困惑所在。
我可以看到你对学习装配的渴望是认真的,并且你在使用堆栈传递变量方面是“创造性的”。
谁知道?也许你已经注意到了一种更好的方式(但我很怀疑它;使用寄存器来做你想做的事情)无论如何,如果我正确猜测,你永远不会在你为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)。