Program to find the maximum number/factor in a list I have written the following basic assembly program to find the maximum number in a list divisible by a number. Here is what I have thus far:
# Program: given a list or integers and a factor
# Find the max number in the list that the factor divides
# For example: INPUT: [3,9,50,27], factor: 3 | OUTPUT: 27
.section .rodata
nums:   .long 3,9,50,27,-1
factor: .long 3

.section .data
cur_value:  .long -1

# first three args: %edi, %esi, %edx
.section .text
.globl _start
_start:

    # SETUP
    # %r8 will store the array index 
    # %r11 will store the max value
    # %esi will store the factor/divisor. 
    mov $0,     %r10d
    mov $0,     %r11d
    mov factor, %esi


loop:
    
    # get current value and store it in %rdi
    # we'll also update our variable for `cur_value`
    mov nums(, %r10d, 4), %edi
    cmp $-1, %edi
    je exit
    movl %edi, cur_value

    # Call the function and increment the aray index
    call is_divisible_by
    inc %r10d

    # if it was NOT divisible (rax = False or 0) jump back to the beginning
    cmp $0, %rax
    je loop

    # if it was divisible, check to make sure it's larger than the current max
    cmp %r11d, cur_value
    jl loop
    mov cur_value, %r11d
    jmp loop
  exit:
    mov %r11d, %edi
    mov $60, %eax
    syscall
    
is_divisible_by:

    # Return 0 (false) if not divisible; 1 (true) if divisible

    # A (dividend, %eax) / B (divisor)
    # dividend needs to first be moved into eax
    mov %edi, %eax 

    # divide by a register, immediate, or memory address
    # this is unsigned (positive), use idiv for signed
    div %esi

    # the resultant integer quotient goes in %eax, and the remainder goes in %edx
    # if %rdx is zero it means A is divisible by B: we don't care about %eax
    mov $0, %eax

    cmp $0, %edx
    jne end
    mov $1, %rax

  end:
    ret


It's compiled using:
$ as file.s -o file.o &amp;&amp; ld file.o -o file
$ ./file; echo $?
# 27

Here are a few particular questions related to this:

Is it common to use named variables (such as cur_value in .section .data) or not? I use them while learning a bit so it's easier to view the value of an easily-rememberable entity, i.e., I can just do x &amp;cur_value in gdb to see what it is.

What is the suggested way to handle an if statement. I've tried to do this in the is_divisible_by function -- setting it to $0 by default and then 'overwriting' it if the true condition is met. -- but this seems pretty hacky. I suppose another way to do it would be something like:
  cmp $0, %edx
  je set_true
set_false:
  mov $0, %eax
  jmp clean_up
set_true:
  mov $1, %eax
  jmp clean_up
clean_up:
  ret


Is it common to have end-labels on functions and such? I find myself often adding an end or whatever to be able to 'exit' things easily.

For labels within a main label (such as exit or end or set_true etc.), what is a good way to name these? I see gcc uses something like .L1029 but that seems not-too-friendly when writing my own and having to remember then.

Would any of the above be better done 'on the stack' rather than using registers or named variables? I find it a bit more difficult to use the stack than registers as you cannot do something like mov mem1, mem2

Finally, how could I extract the is_divisible_by function into another file and call it from within this main file.s file?
You have two independent conditions that must be satisfied before updating cur_val.

The number must be divisible by factor
The number must be larger than cur_val

If the first test fails, you don't bother doing the second test.
How many instruction (or better cycles) does it take to do each test?
Given a long non-monotonic list, you may save considerable time simply by reversing these two tests.