你好,这是我第一次在这里发帖,但我正在做一个家庭作业,就是用这些给定的规则设计一个汇编函数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
最好的方法是使用调试器并逐步完成程序集。然而,有几件事让我眼前一亮:
array
不是一个数组,它只是一个未初始化的DWORD。
push n
push array
这是基于syracuse
访问其参数的方式。一般来说,您的呼叫约定是按push顺序从右到左。如果数组先被压入,它的值将是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
。
我并没有检查你的逻辑是否正确,只是看到了上面的问题。