Finding the maximum of a given list of data in GNU Assembly x86 (32 bit)
In general I try to stick to the naming conventions of the registers themselves. Although, I have been criticized for it because many programmers think of these conventions as archaic. But I think it helps reading the code.


  General-Purpose Registers (GPR) - 16-bit naming conventions[edit] The    8 GPRs are:
  
  
  Accumulator register (AX). Used in arithmetic operations.
  Counter register (CX). Used in shift/rotate instructions and loops.
  Data register (DX). Used in arithmetic operations and I/O operations.
  Base register (BX). Used as a pointer to data (located in segment register    DS, when in segmented mode).
  Stack Pointer register (SP). Pointer to the top of the stack.
  Stack Base Pointer register (BP). Used to point    to the base of the stack.
  Source Index register (SI). Used as a    pointer to a source in stream operations.
  Destination Index register (DI). Used as a pointer to a destination in stream operations.
  


Cited from: https://en.wikibooks.org/wiki/X86_Assembly/X86_Architecture

.section .data
data_1:
    .long 1, 3, 4, 5, 6, 7, 8, 9, 0
data_2:
    .long 23, 45, 62, 13, 87, 54, 0
data_3:
    .long 1, 3, 7, 6, 5, 8, 1, 1, 0

.section .text
.globl _start
.type maximum, @function
.type exit, @function

_start:
    movl    $data_3, %ebx
    call    maximum

exit: 
    movl    %eax, %ebx
    movl    $1, %eax
    int     $0x80

maximum:
    movl    (%ebx), %edx # notice i did not index address here.
    movl    %edx, %eax
    movl    $1, %esi

max_loop:
    cmpl    $0, %edx
    je      exit_loop
    movl    (%ebx, %esi, 4), %edx
    cmpl    %edx, %eax
    cmovng   %edx, %eax
    incl    %esi
    jmp     max_loop

exit_loop:
    ret


Instead of passing the args on the stack, I opted to pass the address in the base register. AMD64 defines way different calling conventions than the original 32bit stuff. If this were a non trivial program we'd definitely want to adhere to the sysv calling conventions which define which registers may be overwritten or must be preserved between calls, stack alignment, etc. In the maximum function we could use a cmov__ instruction if we wanted to conditionally move the data register to the accumulator (current max) if it was greater. 

The next book to get if you want to learn a great deal more about assembly AFTER programming from the ground up is Professional Assembly Language.

Linus Torvalds has criticized cmov instructions because of the out of order execution nature of modern processors. Which the Professional Assembly Language book explains in detail.

http://yarchive.net/comp/linux/cmov.html