0

I'm using ubuntu 32 bits to code in assembly. And I'm trying to do a program to order a string in alphabetical order, but it's not working correctly.

I declared the string. I used lea to place the string in the eax register. Then used movl(%eax), %ebx, to copy the first memory cell (0) of the string that would be the "l", to then compare it with the second memory cell (1) that would be the"h".

In the next cycle, to compare the second memory cell with the third memory cell I did inc %eax so that it would do movl 1(%eax), %ebx instead movl (%eax), %ebx. This is my code:

.data
    str: .string "lhtgbvfmjnbcdsaawcfr"
.text
.globl main
main:
    movl $19, %ecx
inicio:
    leal variavel, %eax
    movl (%eax), %ebx
    cmpl %ebx, 1(%eax) 
    JA maior 
    JB menor
maior:
    xchg %ebx, 1(%eax)
    xchg (%eax), %ebx 
menor:  
    inc %eax 
    decl %ecx 
    cmpl $0, %ecx
    JA inicio 
    JE main

What i did didn't work, so clearly there is something wrong, I've searched about assembly but I haven't found many things. Is there anyone that can help me?

Rafael
  • 7,605
  • 13
  • 31
  • 46
RandomName
  • 23
  • 4
  • 3
    The easiest way to do this is to build a histogram of how often each character occurs and then to generate an array with each character appearing as often as it does in the histogram. – fuz Jan 19 '19 at 22:07
  • 1
    The algorithm @fuz described is Counting Sort, google it. But anyway, this looks broken because it uses `xchg` with 32-bit registers like `%ebx` on addresses only 1 byte apart. Use `movzbl (%eax), %ebx` to load a byte, zero-extended to a dword. (Also note that `xchg` with memory is very slow, because it implies a `lock` prefix to make it atomic.) There are several x86 BubbleSort Q&As on SO. Mostly not AT&T syntax, but you could always assemble them with NASM and then disassemble with `objdump`. – Peter Cordes Jan 19 '19 at 22:22

1 Answers1

1

You're describing a simple Bubble Sort algorithm according to http://en.wikipedia.org/wiki/Bubble_sort:

Bubble sort animation

A ".string" is just an array of characters. The last character has the value 0 to determine the end of the string. A character is coded as an 8-bit-value. So you only need to use the 8-bit registers of the CPU (AL, AH, DL, DH etc.) to handle them. You can use the 32-bit extended registers (EAX, EBX, ECX, EDX etc.), but this complicates things unnecessarily.

Bubble Sort needs two nested loops. In this case an endless outer loop that ends when the string is sorted, and an inner loop that handles every character.

The following example is very simple. For example, the last - sorted - letter is unnecessarily compared again and again. It has a lot of potential for improvement:

#   Name:               bubblesort.s
#   Assemble & link:    gcc -m32 -obubblesort bubblesort.s
#   Run:                ./bubblesort

.data
fmt: .string "%s\n"
str: .string "lhtgbvfmjnbcdsaawcfr"

.text
.global main
main:

    pushl $str                  # Address of str onto the stack
    pushl $fmt                  # Address of fmt onto the stack
    call printf                 # Call libc: printf(fmt,str)
    addl $(4*2), %esp           # Adjust the stack by 2 PUSHes

    O1:                         # Outer loop ends when everything is sorted (swapped == false)
    movl $str, %esi
    movb $0, %dl                # swapped = false

    I1:                         # Inner loop: every character
    movb (%esi), %al
    movb 1(%esi), %ah
    cmpb $0, %ah                # End of string?
    je O2                       # Yes -> exit inner loop

    cmpb %ah, %al               # Compare the characters
    jbe I2                      # If AL < AH, don't swap the characters
    movb $1, %dl                # swapped = true
    movb %al, 1(%esi)           # Swap: Store the characters in reversed order
    movb %ah, (%esi)

    I2:
    incl %esi                   # Next character
    jmp I1

    O2:
    pushal                      # Preserve all registers
    pushl $str                  # Address of str onto the stack
    pushl $fmt                  # Address of fmt onto the stack
    call printf                 # Call libc: printf(fmt,str)
    addl $(4*2), %esp           # Adjust the stack by 2 PUSHes
    popal                       # Restore all registers

    cmpb $1, %dl                # swapped == true?
    je O1                       # Yes -> one more outer loop

    Done:
    ret                         # Return: exit the main function

And here is another "animated" illustration:

https://www.youtube.com/watch?v=lyZQPjUT5B4

rkhb
  • 14,159
  • 7
  • 32
  • 60
  • You should generally avoid using both AH and AL unless you're out of registers, especially if you're not going to do tricks like loading both with a word load, swapping them with `rol $8, %ax` and doing a word store. (Looks like you could use `%cl`). On CPUs other than mainstream Intel (e.g. AMD Ryzen), writing AH has a false dependency on writing AL, because they both merge into the full EAX on write. Also, you could have use `cmp $0, %al` (2 bytes, no worse than `test al,al`) instead of AH. – Peter Cordes Jan 20 '19 at 13:15
  • Bubble Sort is easier to grok if you leave out the early-out "swapped==0" check and just count down the size. Then it's actually pretty straightforward even in asm, like this for integers: [Assembly bubble sort swap](https://stackoverflow.com/q/11497966). See also https://users.cs.duke.edu/~ola/papers/bubble.pdf Bubble Sort: An Archaeological Algorithmic Analysis., – Peter Cordes Jan 20 '19 at 13:19