Assembly 我的项目赢了';对大于130的数组进行t排序
所以我的程序应该接受用户输入(10到200之间的整数),然后打印出一个随机数数组,然后打印出该数组的排序版本。然而,这只在我输入130或更少时有效 我不知道我还能做什么。它起作用了,但只起了一半作用。有没有办法优化这段代码?我已经放置了一些行来帮助显示我遇到的问题 ****我运行了调试器,并在程序抛出异常错误的地方留下了注释*****Assembly 我的项目赢了';对大于130的数组进行t排序,assembly,x86,masm,irvine32,Assembly,X86,Masm,Irvine32,所以我的程序应该接受用户输入(10到200之间的整数),然后打印出一个随机数数组,然后打印出该数组的排序版本。然而,这只在我输入130或更少时有效 我不知道我还能做什么。它起作用了,但只起了一半作用。有没有办法优化这段代码?我已经放置了一些行来帮助显示我遇到的问题 ****我运行了调试器,并在程序抛出异常错误的地方留下了注释***** TITLE Program5 (Program5.asm) INCLUDE Irvine32.inc ; (insert constant defini
TITLE Program5 (Program5.asm)
INCLUDE Irvine32.inc
; (insert constant definitions here)
MIN_INPUT = 10
MAX_INPUT = 200
LO_RANDOM = 100
HI_RANDOM = 999
.data
; (insert variable definitions here)
intro BYTE "Fun with Arrays! by ", 0
instruction BYTE "This program generates random numbers in the range [100 .. 999], displays the original list, sorts the list, and calculates the median value. Finally, it displays the list sorted in descending order", 0
request DWORD 10
ask_user BYTE "How many numbers should be generated? [10 ... 200]: ", 0
error BYTE "Invalid input", 0
title_1 BYTE "The unsorted random numbers: ", 0
title_2 BYTE "The sorted list: ", 0
space BYTE " ", 0
mult DWORD 0.5
temp DWORD 0
list DWORD MAX_INPUT DUP(?)
.code
main PROC
; (insert executable instructions here)
call randomize
call introduction
push OFFSET request ;passed by reference
call getData
call CrLf
push request ; passed by value
push OFFSET list ; passed by reference
call fillArray
push OFFSET list
push request
push OFFSET title_1
call displaylist
call CrLf
push OFFSET list
push request
call sortList
call CrLf
;
push OFFSET list
push request
push OFFSET title_2
call displaylist
;push OFFSET list
;push request
;call displayMedian
exit ; exit to operating system
main ENDP
; (insert additional procedures here)
introduction PROC
mov edx, OFFSET intro
call WriteString
call CrLf
mov edx, OFFSET instruction
call WriteString
call CrLf
ret
introduction ENDP
getData PROC
;include parameter - request (reference)
push ebp ;Set up stack frame
mov ebp, esp
;get an integer from user
mov ebx, [ebp+8] ;get address of request into ebx
L1:
mov edx, OFFSET ask_user
call WriteString
call ReadDec
cmp eax, MIN_INPUT
jl errorMessage
cmp eax, MAX_INPUT
jg errorMessage
cmp eax, MIN_INPUT
jge endThis
cmp eax, MAX_INPUT
jle endThis
errorMessage:
mov edx, OFFSET error
call WriteString
call CrLf
jmp L1
endThis:
mov [ebx], eax
pop ebp
ret 4 ; remove four more bytes from the stack (after ret @)
getData ENDP
fillArray PROC
;include parameters - request (value), array (reference)
; MAJORITY OF THE FOLLOWING CODE WAS EXTRACTED FROM LECTURE 20 SLIDES
push ebp
mov ebp, esp ;[ebp+4]
mov edi, [ebp+8] ; @list in edi
mov ecx, [ebp+12] ; value of request in ecx
more:
mov eax, HI_RANDOM
sub eax, LO_RANDOM
inc eax
call RandomRange
add eax, LO_RANDOM
mov [edi], eax
add edi, 4
loop more
endmore:
pop ebp
ret 8
fillArray ENDP
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
sortList PROC
;include parameters - array (reference), request (value)
push ebp
mov ebp, esp ;[ebp+4]
mov edi, [ebp+12] ; @list in edi
mov ecx, [ebp+8] ; value of request in ecx
dec ecx ; request - 1
mov ebx, 0 ; "k"
;for(k=0; k<request-1; k++) {
;i = k;
;for(j=k+1; j<request; j++) {
;if(array[j] > array[i])
;i = j;
;}
;exchange(array[k], array[i]);
;}
firstLoop:
mov eax, ebx ; "i = k"
mov edx, ebx ; "j = k"
inc edx ; "j = k + 1"
push ecx ; pushed the first loop's counter
mov ecx, [ebp+8] ; made the second loop's counter = request
secondLoop:
mov esi, [edi + (edx * 4)] ; array[j] ; EXCEPTION WAS THROWN HERE
cmp esi, [edi + (eax * 4)] ; compare array[j] and array[i]
jg greater
jle lesser
greater:
mov eax, edx
inc edx
loop secondLoop
lesser:
inc edx
loop secondLoop
push edx
push esi
push [edi + (ebx * 4)] ; array[k]
push [edi + (eax * 4)] ; array[i]
call exchangeElements
pop [edi + (eax * 4)]
pop [edi + (ebx * 4)]
pop esi
pop edx
pop ecx ; set the
inc ebx ; increment k in the first loop
loop firstLoop
pop ebp
ret 8
sortList ENDP
exchangeElements PROC
push ebp
mov ebp, esp
mov esi, [ebp+12] ; array[k]
mov edx, [ebp+8] ; array[i]
mov [ebp+8], esi
mov [ebp+12], edx
pop ebp
ret
exchangeElements ENDP
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
displayMedian PROC
push ebp
mov ebp, esp ;[ebp+4]
mov edi, [ebp+12] ; @list in edi
mov ecx, [ebp+8] ; value of request in ecx
mov eax, ecx
mov ebx, 2
cdq
div ebx
cmp edx, 0
je isEven
cmp edx, 1
je isOdd
;def nlogn_median(l):
;l = sorted(l)
;if len(l) % 2 == 1:
;return l[len(l) / 2]
;else:
;return 0.5 * (l[len(l) / 2 - 1] + l[len(l) / 2])
isEven:
mov esi, [edi + (eax - 1)]
add esi, [edi + (eax)]
mov eax, esi
mov ebx, 2
cdq
div ebx
call WriteDec
isOdd:
mov eax, [edi + (eax*4)]
call WriteDec
pop ebp
ret
displayMedian ENDP
displayList PROC
push ebp
mov ebp, esp ; [ebp+4]
mov ecx, [ebp+12] ; @request
mov edi, [ebp+16] ; @list
mov esi, 10
mov edx, [ebp+8] ; @title
call WriteString
call CrLf
show:
mov eax, [edi]
call WriteDec
mov edx, OFFSET space
call WriteString
add edi, 4
dec esi
cmp esi, 0
je callClear
loopAgain:
loop show
jmp endshow
callClear:
mov esi, 10
call CrLf
jmp loopAgain
endshow:
pop ebp
ret 12
displayList ENDP
END main
标题程序5(Program5.asm)
包括Irvine32.inc
; (在此处插入常量定义)
最小输入=10
最大输入=200
LO_RANDOM=100
HI_RANDOM=999
.数据
; (在此处插入变量定义)
简介字节“数组的乐趣!由”,0
指令字节“此程序生成[100..999]范围内的随机数”,显示原始列表,对列表进行排序,并计算中值。最后,按降序显示列表”,0
请求DWORD 10
询问用户字节“应生成多少个数字?[10…200]:”,0
错误字节“无效输入”,0
标题_1字节“未排序的随机数:”,0
标题_2字节“排序列表:”,0
空格字节“”,0
多德沃德0.5
临时DWORD 0
列出DWORD最大输入DUP(?)
.代码
主进程
; (在此处插入可执行指令)
呼叫随机化
电话介绍
推送偏移请求;参照传递
调用getData
呼叫CrLf
推送请求;按值传递
推送偏移列表;参照传递
调用填充数组
推送偏移列表
推送请求
推送偏移标题_1
呼叫显示列表
呼叫CrLf
推送偏移列表
推送请求
呼叫分拣员
呼叫CrLf
;
推送偏移列表
推送请求
推送偏移标题2
呼叫显示列表
;推送偏移列表
;推送请求
;呼叫显示中位数
出口退出操作系统
主端
; (在此插入其他程序)
介绍过程
mov edx,偏移量介绍
通话记录
呼叫CrLf
偏移指令
通话记录
呼叫CrLf
ret
导言
获取数据过程
;包含参数-请求(参考)
推动ebp;设置堆栈框架
电动汽车
;从用户处获取整数
mov-ebx,[ebp+8];将请求地址获取到ebx中
L1:
mov edx,偏移量询问用户
通话记录
呼叫ReadDec
cmp eax,最小输入
jl错误消息
cmp eax,最大输入
jg错误消息
cmp eax,最小输入
jge endThis
cmp eax,最大输入
jle endThis
错误消息:
偏移量误差
通话记录
呼叫CrLf
jmp-L1
完此:
mov[ebx],eax
流行ebp
ret4;从堆栈中再删除四个字节(在ret@之后)
getData ENDP
填充数组过程
;包括参数-请求(值)、数组(参考)
; 以下大部分代码摘自第20课的幻灯片
推ebp
mov-ebp,esp;[ebp+4]
移动电子数据交换[ebp+8]@电子数据交换中的列表
mov-ecx,[ebp+12];ecx中请求的值
更多:
mov-eax,HI_-RANDOM
子eax,LO_随机
埃克斯公司
呼叫随机范围
加上eax,lou随机
mov[edi],eax
添加edi,4
循环更多
endmore:
流行ebp
ret 8
fillArray ENDP
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
排序程序
;包括参数-数组(参考)、请求(值)
推ebp
mov-ebp,esp;[ebp+4]
移动电子数据交换[ebp+12]@电子数据交换中的列表
mov-ecx,[ebp+8];ecx中请求的值
dec-ecx;请求-1
mov-ebx,0;“k”
;对于(k=0;k如果你查看你的寄存器,你会发现edx
是0fA4h
,它比它崩溃时所在的行要大。ecx
是一个负数。这是循环应该停止后执行的线索
问题是较大的
分支将通过较小的
分支。这将再次减小ecx
,导致其变为负值,循环将继续运行,直到您获得访问冲突
快速修复方法是在更大的标签下的循环
指令之后放置一个无条件的jmp
更好的解决方法是将循环的尾部组合成更简单的条件:
cmp esi, [edi + (eax * 4)] ; compare array[j] and array[i]
jle lesser
mov eax, edx
lesser:
inc edx
loop secondLoop
确切地说是130吗?如果你在某处截短到字节,127是最大的有符号字节,128或更高可能“看起来像”一个负数。当你的代码出错时,寄存器中的值是什么?EDI中的基是否正确,EDX中的索引是否在范围内?它是否在第一次迭代时出错,或者由于某种原因在循环结束数组后出错?如果我输入130,则程序打印出130个随机数的数组。然后打印出相同的数组,但从最大值到最小值排序。如果我在131中输入,则在屏幕上打印出未排序的数组后,程序崩溃。我将发布寄存器值的屏幕截图。在您逐步查看发生了什么情况后,调试器会告诉您什么?调试器还应告诉您指令是否访问了错误地址。当它输入s second循环,它会被卡住一段时间,然后停止程序并抛出异常0x0040a000
是新页面的开始,因此