2016-07-11 5 views
0

Ich verstehe ehrlich nicht, was ist falsch mit meinem Programm. Es druckt -5 als den größten Wert in dem Array. Das ist natürlich völlig falsch. Es sollte sein 34. Ich denke, das Problem auf jeden Fall irgendwo hier liegt:Ich verstehe nicht, was ist falsch mit der Art, wie ich vergleiche (Cmpl)

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

Stimmt etwas nicht mit der Art, wie ich den Vergleich mache, mich dünkt. Dies ist ein leicht überarbeitetes Beispiel aus diesem Buch: 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 

Um das Programm zu kompilieren, verwenden Sie diesen Befehl:

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' ist unsigniert, Sie wollen' cmovg'. Siehe eine Befehlssatzreferenz. – Jester

Antwort

3

Als jemand sagte, cmova Kontrollen für „oben“, die Werte wie behandelt unsigniert. Wenn Sie Ihre Zahlen als unsigned behandeln, wird -5 interpretiert als 0xFFFFFFFB, die weit höher als 34 ist (und auch höher als -45 oder 0xFFFFFFD3). Dieser Wert "gewinnt" und wird erneut als signierte Nummer angezeigt (d. H. -5).

Wenn Sie vorzeichenbehaftete Zahlen vergleichen möchten, verwenden Sie stattdessen cmovg.

+1

Immer daran denken: -a ist oben, -b ist unten; beide nicht signiert. -g ist größer und -l ist weniger; beide unterschrieben. –

Verwandte Themen