简体   繁体   中英

I don't understand what's wrong with the way I'm doing comparison (cmpl)

I honestly don't understand what is wrong with my program. It prints -5 as the largest value in the array. Of course, that is totally wrong. It should be 34. I think the problem definitely lies somewhere here:

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

Something wrong with the way I'm doing the comparison, methinks. This is a slightly reworked example from this book: 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

To compile the program, use this command:

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

As someone said, cmova checks for "above", which treats values as unsigned . If you treat your numbers as unsigned , -5 is interpreted as 0xFFFFFFFB , which is far higher than 34 (and also higher than -45 , or 0xFFFFFFD3 ). So that value "wins", and is displayed as signed number again (ie -5 ).

If you want to compare signed numbers, use cmovg instead.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM