assembly x86程序集-查找已排序数组中的最大值

oxcyiej7  于 2022-11-13  发布在  其他
关注(0)|答案(1)|浏览(152)

两天前我发布了一个关于我在x86汇编中遇到的问题(谢天谢地,我能够通过使用冒泡排序方法从最小到最大进行排序来修复(大部分))。我成功地对我拥有的两个数组进行了排序(如下面我的代码的数据部分片段所示),但选择每个数组中的最大值成为一个问题。

INCLUDE Irvine32.inc

.data
Array1  DWORD 0C0D12AFh, 00030256h, 0FFAABBCCh, 0F700F70h, 00000000h, 0E222111Fh, 0ABCDEF01h, 01234567h
Array2  DWORD 61A80000h, 024F4A37h, 0EC010203h, 0FAEEDDCCh, 2C030175h, 84728371h, 63AA5678h, 0CD454443h, 22222222h, 61B1C2D3h, 7A4E96C2h, 81002346h, 0FDB2726Eh, 65432100h, 0FFFFFFFFh

问题可能出在我呼叫程序以选取最大值之前的区段(在我程式码的主要程序中):

.code
main PROC
    .....

    ; display Array1 + get and display greatest value in Array1
    call displayArray1          ; display Array1 (sorted)
    call Crlf                   ; skip line
    mov  esi,OFFSET Array1      ; point to start of Array1
    mov  ecx,LENGTHOF Array1-4  ; number of units
    call getLargest             ; find largest value in Array1 and
                                ;   display it
    ; display Array2 + get and display greatest value in Array2
    call displayArray2          ; display Array2 (sorted)
    call Crlf                   ; skip line
    mov  esi,OFFSET Array2      ; point to start of Array2
    mov  ecx,LENGTHOF Array2-4  ; number of units
    call getLargest             ; find largest value in Array2 and
                                ;   display it
    
    exit                        ; exit the program
main ENDP

在这里我首先调用这些过程来显示排序后的两个数组,然后将数组指针移动到寄存器中,并调整ECX,使其停止在数组中最后一个值之前的一个位置--mov ecx,LENGTHOF Array1-4mov ecx,LENGTHOF Array2-4--或者,我的问题在于 getLargest 过程本身(其中扫描数组以查找其最大值(在本例中应为数组的最终值)):

;-------------------------------------------------------
getLargest PROC
;
; Finds and returns a statement of what the greatest
;   value in an array is.
; Receives: nothing
; Returns: statement of largest value in array
;-------------------------------------------------------
    mov  eax,[esi]          ; move pointer into EAX
    sift:
        cmp  [esi+4],eax        ; compare next value and EAX
        jng  skip               ; if EAX >= [ESI+4], skip
        mov  eax,[esi+4]        ; else, mov [ESI+4] into EAX
    skip:
        add  esi,4              ; increment ESI by 4
        dec  ecx                ; decrement ECX
        jnz  sift               ; if ECX not zero, jump back to sift
        mov  ebx,eax            ; signed maximum
    quit:
        ; display largest unsigned integer
        mov  edx,OFFSET largestUnsignedS
        call WriteString        ; display largestUnsignedF string
        mov  eax,ebx
        call WriteHex           ; display largest unsigned value
        mov  edx,OFFSET largestUnsignedF
        call WriteString        ; display largestUnsignedS string
        call Crlf               ; skip line
        ret
getLargest ENDP

目前,我收到的输出显示Array1中的最大值为0 F700 F70 h(此时应为FFAABBCCh),且Array2中的最大值为7A 4 E96 C2 h(当它应该是FFFFFFFFh时)。我认为该过程要么在每个数组的最终位置前停止几个位置(由于语法原因)或过程运行了正确得次数,但未能在正确得时间在siftskip循环之间跳转.
好消息是我没有收到错误(因为构建过程可能会失败),但我没有收到 getLargest 的正确输出。本质上,我想知道的是我是否需要修复main中发送给ECX的内容,或者我是否需要修复 getLargest 中的循环。

mspsb9vt

mspsb9vt1#

引用我之前的回答:
查找最大元素的代码如下所示:

mov  eax, 80000000h ; Smallest signed dword
More:
 cmp  [esi], eax
 jng  Skip
 mov  eax, [esi]
Skip:
 add  esi, 4
 dec  ecx
 jnz  More
 mov  ebx, eax        ; The signed maximum

新的 getLargest proc建立在这个基础上,甚至通过使用第一个数组元素初始化EAX来优化它。这可以减少循环的1次迭代。为此,您选择了在ECX寄存器中传递一个较小的计数。错误在mov ecx, LENGTHOF Array1-4中。由于LENGTHOF提供了数组元素的数量,因此您需要减去1。
实际上,我想知道的是,我是否需要在 main 中修复发送到ECX的内容,或者我是否需要在 getLargest 中修复循环。
我不会更改ECX参数:

  • 看到这种修复的读者会更加困惑
  • 这与调用BubbleSort过程的方式不同
  • 在proc中,减量可以检测0或1个元素的平凡情况

我的建议

; IN (ecx,esi)
getLargest PROC
    xor  eax, eax
    dec  ecx
    js   quit               ; return 0 for empty array
    mov  eax, [esi]         ; Arr[0]
    jz   quit               ; return Arr[0] for single-element array
sift:
    cmp  [esi+4], eax       ; compare next value and EAX
    jng  skip               ; if EAX >= [ESI+4], skip
    mov  eax, [esi+4]       ; else, mov [ESI+4] into EAX
skip:
    add  esi, 4
    dec  ecx
    jnz  sift               ; if ECX not zero, jump back to sift
quit:
    mov  ebx, eax           ; signed maximum
    ...

改进您的评论

getLargest PROC  
; Receives: nothing
  • nothing* -您得proc接收ECX与ESI寄存器.
mov  eax,[esi]          ; move pointer into EAX
  • pointer* -你正在加载第一个数组元素的值。对我来说,你的数组看起来不像是包含指针的内容。

已签名与未签名

目前,我收到的输出显示 * Array 1 * 中的最大值为0 F700 F70 h(此时它应该是FFAABBCCh),* Array 2 * 中的最大值为7A 4 E96 C2 h(此时它应该是FFFFFFFFh)
您的期望是错误的!因为您的筛选代码使用的是signed条件分支指令jng JumpIfNotGreater,所以像FFAABBCCh和FFFFFFFFh这样的数字被视为负数,不会使其成为“最大”。
因此,要让程序筛选无符号值数组,请使用unsigned条件分支指令jna JumpIfNotAbove。

相关问题