Я не понимаю, что не так с тем, как я делаю сравнение (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
вместо.