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.