【问题标题】:problems with stack in NASMNASM 中的堆栈问题
【发布时间】:2013-05-04 18:40:32
【问题描述】:

我正在用 NASM 编写一个计算斐波那契数列并打印出来的程序。它接受用户输入的两个种子值和迭代次数,将它们存储在堆栈中,然后调用“fib”子例程进行计算和打印。我正在使用来自here 的库来执行读取输入/打印等操作。

这是我的 asm_main:

asm_main:
        enter   0,0                 ; setup routine
        pusha

    mov eax, prompt1        ; access first prompt
    call    print_string        ; print prompt
    call    read_int        ; read input and stores in eax
    push    eax         ; store input on stack

    mov eax, prompt2        ; access second prompt
    call    print_string        ; print prompt
    call    read_int        ; read input and stores in eax
    push    eax         ; store input on stack

    mov eax, prompt3        ; access third prompt
    call    print_string        ; print prompt
    call    read_int        ; read input and stores in eax
    push    eax         ; store input on stack

    call    fib         ; call fib subroutine to calculate sequence
    call    print_nl        ; end with a newline

这里是 fib 子程序:

fib:
    pop ecx         ; retrieve number of iterations from stack
    pop ebx         ; retrieve second seed value from stack
    pop eax         ; retrieve first seed value from stack

    _looper:            ; section to be looped
        mov edx, eax
        add edx, ebx    ; sum = a + b
        call    print_int
        call    print_nl
        mov eax, ebx    ; a = b
        mov ebx, edx    ; b = sum
        loop _looper
    ret

但是,这种推送和弹出操作无法正常工作,我不知道为什么。当我输入“3”作为第一个种子值,“5”作为第二个种子值,并输入“7”作为迭代次数时,这是在 fib 中调用的寄存器转储的结果:

Register Dump # 1
EAX = 00000005 EBX = 00000007 ECX = 080484D4 EDX = BF97A1B4
ESI = 00000000 EDI = 00000000 EBP = BF97A168 ESP = BF97A144
EIP = 08048480 FLAGS = 200282       SF 

我在这里遗漏了什么吗?根据我的理解,堆栈应该是后进先出的,我无法弄清楚出了什么问题。谢谢

【问题讨论】:

    标签: assembly stack nasm


    【解决方案1】:

    当您 call fib 然后在 fib 内部时,您将从堆栈中弹出的第一件事就是返回地址。只要您确保在弹出参数后将其重新打开,就可以将其弹出,否则最后的 ret 指令会将您发送到您不想要的地方。

    你可能会这样做

    fib:
        pop edx         ; pop return address
        pop ecx         ; retrieve number of iterations from stack
        pop ebx         ; retrieve second seed value from stack
        pop eax         ; retrieve first seed value from stack
        push edx        ; put return address back on stack
        ...
    

    但更传统的方法是设置堆栈帧

        push ebp
        mov ebp, esp
    

    然后使用

    访问参数
        mov ecx, [ebp+8]
        mov ebx, [ebp+12]
    

    等等

    然后在最后弹出栈帧和参数:

        mov esp, ebp
        pop ebp
        ret 12
    

    后一种方法允许您在需要时访问参数 - 而不仅仅是在进入例程时。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-17
      • 2017-02-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-13
      • 1970-01-01
      相关资源
      最近更新 更多