INT_MAX equ 7FFF_FFFFh
SECTION .text
global find_smallest_int
find_smallest_int:
; If the array is empty (size = 0) then we want to return
; without reading from the array at all. The value to return
; then logically should be the highest possible number for a
; 32-bit signed integer. This is called INT_MAX in the C
; header limits.h and for 32-bit int is equal to 7FFF_FFFFh.
;
; If the array is not empty, the first iteration will then
; always leave our result register equal to the value in
; the first array entry. This is either equal to INT_MAX
; again, or less than that.
mov eax, INT_MAX
; esi is the second argument to our function, which is
; declared as int find_smallest_int(int *, unsigned int).
; It represents the length of the array. We use this
; as a counter. rsi (and its part esi) need not be preserved
; across function calls for the AMD64 psABI that is used by
; Linux, see https://stackoverflow.com/a/40348010/738287
; Check for an initial zero value in esi. If this is found,
; skip the loop without any iteration (while x do y) and
; return eax as initialised to INT_MAX at the start.
test esi, esi
jz .end
.loop:
; If eax is greater than or equal to dword [rdi], we'll
; reassign eax to that dword, the new smallest-yet value.
cmp eax, dword [rdi]
cmovge eax, dword [rdi]
; Set rdi to point to the next value in the array.
add rdi, 4
; Subtract one from our counter. This started as
; the number of elements in the array - when it
; gets to 0, we'll have looped through the entire thing.
dec esi
; Check to see if we've reached the end of the array.
; To do this, we use the Zero Flag as set by the prior
; dec instruction. If esi has reached zero yet (ZR) then
; we do not continue looping. In that case, we return the
; smallest value found yet (which is in eax at the moment).
;
; Else, we jump to the start of the loop to begin the next
; iteration.
jnz .loop
.end:
retn