Я не понимаю, что не так с тем, как я делаю сравнение (cmpl)

Честно говоря, я не понимаю, что не так с моей программой. Это печатает -5 как самое большое значение в массиве. Конечно, это совершенно неправильно. Это должно быть 34. Я думаю, что проблема определенно лежит где-то здесь:

            cmpl        %ebx, %eax                 # Compare max and value
            cmova       %eax, %ebx                 # If eax > ebx, it's new max

Что-то не так с тем, как я делаю сравнение, я думаю. Это слегка переработанный пример из этой книги: Professional Assembly Language by Richard Blum (2005)

/******************************************************************************
 * max.s                                                                      *
 * =====                                                                      *
 *                                                                            *
 * Assembler: the GNU Assembler                                               *
 *                                                                            *
 *                                                                            *
 *                                                                            *
 * Description:                                                               *
 *                                                                            *
 * This program finds the largest integer in a series defined in an array.    *
 *                                                                            *
 ******************************************************************************/

# Constants
.equ DATA_SIZE,    4 # The size in bytes of each element in the array
.equ ARRAY_LENGTH, 6 # The length of the array
.equ EXIT_SUCCESS, 0 # The exit status code 0 means successful execution


.globl _start

################################################################################

.section   .data
msg:       .asciz       "Largest value is %d\n"    # Output string
a:         .long        10, -5, -45, 4, 34, 6      # Array of 6 elements


################################################################################

.section   .text
_start:     movl        a, %ebx                    # Save first element as max
            movl        $1, %edi                   # Start iterating at index 1
loop:       movl        a(, %edi, DATA_SIZE), %eax # Load the value
            cmpl        %ebx, %eax                 # Compare max and value
            cmova       %eax, %ebx                 # If eax > ebx, it's new max
            inc         %edi                       # Increment the index
            cmpl        $ARRAY_LENGTH, %edi        # If not reached the end,
            jne         loop                       # keep looping

            # Print the result
            pushl       %ebx                       # Second argument
            pushl       $msg                       # First argument
            call        printf                     # Call C's printf function
            addl        $8, %esp                   # Clean the stack

            # Exit the program
            pushl       $EXIT_SUCCESS              # Exit status code
            call        exit                       # Call C's exit function

Чтобы скомпилировать программу, используйте эту команду:

as --32 -gstabs max.s -o max.o && \
ld -m elf_i386 -dynamic-linker /lib/ld-linux.so.2 -o a.out -lc max.o && \
rm max.o && ./a.out

1 ответ

Решение

Как кто-то сказал, cmova проверяет "выше", что рассматривает значения как беззнаковые. Если вы относитесь к своим номерам как без знака, -5 интерпретируется как 0xFFFFFFFB, что намного выше, чем 34 (а также выше, чем -45, или же 0xFFFFFFD3). Так что значение "выигрывает" и снова отображается как число со знаком (т.е. -5).

Если вы хотите сравнить числа со знаком, используйте cmovg вместо.

Другие вопросы по тегам