2014-10-10 52 views
0

在汇编中,'pop'命令用于返回指定的值吗?我似乎无法使其正常工作。我尝试打印输入以查看输入是否已更改,但是在再次等待用户输入之前,程序会循环两次。在Assey中,我的函数试图返回一个值是否有问题?

数据声明:

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 

我在我的子程序'function'中的扫描程序中做错了什么?谢谢你能帮助我的人。刚开始学习Assembly的子程序,我无法弄清楚这个。一直呆在这个简单的bug现在一个小时。

+0

通常'pop'不用于返回,'mov eax,SOMETHING'是。但是这看起来像手写的asm,并没有遵循任何标准的调用约定。 – o11c 2014-10-10 04:20:03

回答

0

好吧,让我看看我是否猜测你误解的地方,并帮助你清除它。

你已经听到了一个被熟悉的东西嘲笑的短语,它会像这样“该堆栈用于在函数之间传递变量。”是的,这是真的;但并不完全正确,它已经让你的生活充满困惑。

我还假设你在C和程序集的上下文中思考。

好吧,关于C,函数有一个“类型”,因为我猜你知道。

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

(我们会坚持使用x86这里,虽然它一般适用于一堆别人的真)

汇编语言,你有呼叫指令,以及惩戒指令,这是关于它。

哦,是的,你在x86和其他一些类似的芯片上也有Int指令;但就目前而言,我们只会将重点放在致电Ret

所以无论如何,这个BIZ的“堆栈上传递参数”是(在C中的至少)约总是设定为使

  • 参数被传递TO堆栈
  • 在功能上
  • 值返回FROM功能在寄存器

我想这就是你的困惑我秒。

我可以看到,你对学习汇编的愿望很认真,而且在使用堆栈来传递变量时,你是“有创意”的。

谁知道?也许你已经注意到了一种更好的方式(但我认真地怀疑它;使用寄存器来处理你正在尝试做的事情)

无论如何,如果我正确猜测,你绝不会在堆栈中写入任何东西你创建的function填充

这是你要做什么来确认或否认这一点。

调试这个由单在每个这三个指令断点踩着它...

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

打开一个观察窗口和观察[ESP]前后call function指令之后的存储位置。

我想你会发现你从来没有写入任何东西到那个位置。

再次,虽然这个概念可能在这种情况下工作,但它通常是一个不太好的想法尝试;所以省去很多麻烦,并在寄存器中返回一个值。

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

不知道这是否有帮助,但我试过。

0

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

例如,在cdecl调用约定在C中是这样工作的:

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)大文章。

相关问题