2016-07-11 1 views
0

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

  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 
+2

'cmova' является неподписанным, вы хотите' cmovg'. См. Ссылку на набор инструкций. – Jester

ответ

3

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

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

+1

Всегда помните: -a выше, -b ниже; оба без знака. -g больше, а -l меньше; оба подписаны. –

Смежные вопросы