0

因此,我们目前正在研究教授向我们展示的英特尔 8086 插入排序代码。他想让我们弄清楚为什么代码会从他从网上获取的代码中跳过数组中的第 0 个元素和数组中的第 3 个元素。

; void isort(int *a, int n)
;   sorts the first n elements of a
;
; Parameters
;   a - pointer to the array
;   n - number of elements to sorts

%define a [ebp + 8]
%define n [ebp + 12]
isort:
  enter 0, 0
  pusha

  mov ecx, 1
  for:
    mov ebx, ecx
    imul ebx, 4
    add ebx, a
    mov ebx, [ebx]

    mov edx, ecx
    dec edx

    while:
      cmp edx, 0
      jl while_quit

      mov eax, edx
      imul eax, 4
      add eax, a

      cmp ebx, [eax]
      jge while_quit

      mov esi, [eax]

      mov dword [eax + 4], esi

      dec edx
      jmp while
    while_quit:

    mov [eax], ebx

    inc ecx
    cmp ecx, n
    jl for

  popa
  leave
  ret

样本数组为 {5, 8, 12, 2, 1, 7}。自从我们几天前刚开始以来,这更有助于理解 8086 语言,我想知道是否有人可以解释如何以及可能出了什么问题。

4

1 回答 1

0

ECX考虑当为 1时代码会做什么:

  • 将使用和while进入循环。EBX=8EDX=0
  • jl while_quit不会被采用,因为是EDX0。
  • EBX与 相比[EAX]。那是; 8 与a[0]5 进行比较,因此jge while_quit采用 。
  • mov [eax], ebx将 8 个存储在a[0],因此您的数组现在包含{8,8,12,2,1,7}。显然不是您想要的,因为您丢失了原始元素之一。

除了代码的逻辑缺陷之外,这些imul指令完全没有必要,因为您可以在 x86 上使用缩放索引。所以排序代码可以简化为(我已经验证它对数组进行了正确排序):

mov ecx, 1
for_:
  ; esi = &a[holePos]   
  lea esi,[a + ecx*4]
  ; valueToInsert = a[holePos]
  mov ebx, [esi]

  while_:
    ; Did we reach the beginning of the array?
    cmp esi, OFFSET a
    jle while_quit

    ; valueToInsert < a[holePos-1] ?
    cmp ebx, [esi-4]
    jge while_quit

    ; a[holePos] = a[holePos-1]
    mov eax, [esi-4]
    mov [esi], eax

    ; esi = &a[holePos-1]
    sub esi,4
    jmp while_
  while_quit:

  ; a[holePos] = valueToInsert
  mov [esi], ebx

  inc ecx
  cmp ecx, 6
  jl for_

我正在使用 MASM 语法,但你明白了。

于 2013-07-29T07:58:02.153 回答