1

Write simple buble sort in nasm x86.

%include "io.inc"

section .bss
n resd 1
arr resd 1000000

section .text
global main
main:
    mov ebp, esp; for correct debugging
    GET_UDEC 4, n
    xor ecx, ecx
    xor esi, esi
    mov edi, 1
l1:
    cmp ecx, [n]
    je l2
    GET_DEC 4, [arr + ecx * 4]
    inc ecx    
    jmp l1
l2:
    mov ecx, -1
l4:    
    inc ecx
    cmp ecx, [n]
    je l3
    mov ebx, -1
l6:
    inc ebx
    cmp ebx, [n]
    je l4
    mov eax, [arr + ebx * 4]
    inc ebx
    mov edx, [arr + ebx * 4]
    dec ebx
    cmp edx, eax
    jl l5
    jmp l6
l5:
    xchg edx, eax
    mov [arr + ebx * 4], eax
    inc ebx
    mov [arr + ebx * 4], edx
    dec ebx
    jmp l6
l3:
    cmp esi, [n]
    je l7
    mov eax, [arr + esi * 4]
    PRINT_DEC 4, eax
    PRINT_STRING " "
    inc esi
    jmp l3
l7:   
    xor eax, eax
    ret
Sep Roland
  • 33,889
  • 7
  • 43
  • 76
  • 2
    Open your program in a debugger, set a breakpoint at `l1:` and investigate what value is in `ecx`, `[n]`, `[arr]`. Or let the program run and investigate `ebx` at the moment when it reports the error in accessing memory. – vitsoft Apr 02 '23 at 12:24
  • 3
    Use meaningful label names, like this it's much harder for us to know what is going on. – m0skit0 Apr 02 '23 at 12:30
  • Please clarify your specific problem or provide additional details to highlight exactly what you need. As it's currently written, it's hard to tell exactly what you're asking. – Community Apr 02 '23 at 15:05

1 Answers1

1

Your code suffers from the famous 'one-off' problem

Bubble-sorting an array is not needed for an array with just 1 or 0 elements.
Your program is correct for an empty array, but in case there is but 1 element you allow the code to enter the InnerLoop at L6. There you will be comparing 2 adjacent dwords from memory. Obviously, that second dword is not part of the array.

The quickest fix you could apply, would be to temporarily decrement the number of elements from the n variable:

l2:
    dec dword [n]        <<<<
    js  l3               <<<<
    mov ecx, -1
l4:

    ...

l3:
    inc dword [n]        <<<<
    cmp esi, [n]
    je l7

The sensible fix would be to re-think it entirely.

  • Your current InnerLoop always runs through the same number of elements. This is wasteful because in BubbleSort at the end of each InnerLoop the last element will be at its final place and therefore it doesn't need your attention any more. So the InnerLoopCount (EDX) should be initialized to be equal to the current OuterLoopCount (ECX).

  • Always prefer the simpler addressing modes; instead of that scaled index addressing mode, use [esi], and because the array elements that are to be compared are always adjacent to each other you can address the other element with a simple offset of plus 4 like in [esi + 4].

Find out how next code works before you should copy it!

  mov  ecx, [n]
  sub  ecx, 1
  jbe  Done            ; Array is empty or has but 1 element

OuterLoop:
  mov  edx, ecx        ; eg. 5 elements means 4 comparisons
  mov  esi, arr
InnerLoop:
  mov  eax, [esi]
  mov  ebx, [esi + 4]
  cmp  eax, ebx
  jle  NoSwap
  mov  [esi], ebx
  mov  [esi + 4], eax
NoSwap:
  add  esi, 4
  dec  edx
  jnz  InnerLoop
  dec  ecx             ; eg. Next time 3 comparisons, then 2, and then 1
  jnz  OuterLoop

Done:
Sep Roland
  • 33,889
  • 7
  • 43
  • 76