【问题标题】:x86 assembly procedure crashes, possibly overlooking simple errorx86 汇编程序崩溃,可能忽略了简单的错误
【发布时间】:2013-05-03 18:50:19
【问题描述】:

您好,这是我第一次在这里发帖,但我正在做一个家庭作业,即使用以下给定规则设计一个汇编函数 syracuse(N, sequence): 1.如果N为1,结束循环。 2.如果N为偶数,则N=N/2,跳转到循环开头 3.如果N为奇数,则N=3N+1,跳转到循环开头

很简单,然后他希望我们显示一些信息并创建报告。但是,我已经盯着这段代码几个小时了,我不知道出了什么问题。一旦我注释掉调用,程序运行良好,不会崩溃,否则会崩溃。我想我只是忽略了一些简单而基本的东西,你们中的任何人都可以提供帮助吗?

代码如下:

.586
.MODEL FLAT
INCLUDE io.h   
cr  EQU 0dh;carriage return
Lf  EQU 0ah;line feed 
.STACK  4096
.DATA
array   DWORD ?
n       DWORD   0
steps   DWORD   0   
prompt  BYTE    "Enter N: ", 0
count   BYTE    cr, Lf, "Total Numbers: "
string  BYTE    40 DUP (?)
result  BYTE    cr, Lf, "N: "

;result2    BYTE    cr, Lf, "Steps: "
lbl BYTE 11 DUP (?)
BYTE cr, Lf, 0
.CODE
_start    PROC
    output prompt ;ask for n
    input string, 40
    atod string ; convert to int
    mov n, eax  
    dtoa lbl, n ;convert to ascii
    output result; print out n

    push n
    push array
    call syracuse
    add esp, 8
    ret
_start    ENDP
syracuse PROC ; syracuse(n, array)
    push ebp
    mov ebp, esp
    push ebx;save ebx
    push eax;save eax
    push esi
    mov eax, [ebp+8] ;first parameter 
    lea esi, [ebp+12] ;beginning of the array
            mov ecx, 0
    whileLoop:  inc ecx; ecx++
                mov [esi+4], eax
                cmp eax, 1
                je endLoop ;if n = 1, then end
                mov ebx, 2
                idiv ebx
                cmp edx, 0
                je evenProc ; if n is even

                ;if n is odd then 3N + 1
                shl eax, 1
                add eax, 2
                jmp whileLoop               
    evenProc: ;if n is even then N = N/2
        mov ebx, 2
        idiv eax
        jmp whileLoop
    endLoop:
        dtoa lbl, ecx
        output count;display count
        pop esi
        pop eax
        pop ebx
        pop ebp
        ret

syracuse ENDP
END

【问题讨论】:

    标签: assembly x86 intel


    【解决方案1】:

    最好的办法是使用调试器并逐步检查您的程序集。但是,我突然想到了一些事情:

    array 不是一个数组,它只是一个未初始化的 DWORD。

    push n  
    push array
    

    这是基于syracuse 访问其参数的方式倒退的。通常,您的调用约定是从右到左的推送顺序。如果数组先入栈,则其值为 EBP+12,n 为 EBP+8。

    mov [esi+4], eax
    

    ESI = EBP+12。因此,[ESI+4] = [EBP+16] 并且该堆栈位置可能存储了 start 调用者的返回地址;改变它可能不是一个好主意。由于array 并不是一个真正的数组,而且您每次都写入同一个位置,您可能可以完全跳过使用 ESI 并改用 mov [ebp+12], eax(尽管您似乎完全放弃了该值;也许您想将array 的地址压栈?)。

    idiv ebx
    

    在本例中,idiv 指令将 64 位整数 EDX:EAX 除以操作数 EBX。由于您不清除 EDX,因此您可能无法得到您想要的结果(包括整数溢出异常)。在idiv 之前尝试xor edx, edx。

    我并没有真正检查您的所有逻辑是否正确,只是看到了上述问题。

    【讨论】:

    • 太棒了,你解决了我的崩溃问题!非常感谢您的帮助,而不是因为我犯了愚蠢的错误而抨击我!
    • @JamesLittle 如果答案解决了您的问题,请确保您接受!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-24
    • 2012-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多