'Finding the minimum value on a list Assembly Language GAS

I'm trying to find the minimum value of a list using assembly language. I'm trying to use -1 to compare all the other values to. my current code is

data_items:
.byte 3,67,34,222,45,75,54,34,44,33,22,11,66,-1
.section .text
.global _start
_start:
movb $0, %rdi
movb data_items(,%rdi,1),%al
movb %al, %bl

start_loop:
cmpb $-1, %al
je loop_exit
inc %edi
movb data_items(,%rdi,1), %al
cmpb %bl, %al
jle start_loop

movb %al, %bl
jmp start_loop
loop_exit:

movb $1, %al
int $0x80

I keep getting 97 as the output and I'm pretty stuck. Can anyone tell me where I'm wrong? Assembly language is brutal.



Solution 1:[1]

Your code has two problems.

First, using jle start_loop, you jump to start_loop when al <= bl. But, since %al is the new number to check and %bl is the lowest number found up to now, what you should do is jg start_loop, that is: jump when al > bl and thus we haven't found a number less than the minimum.

data_items:
.byte 3,67,34,222,45,75,54,34,44,33,22,11,66,-1
.section .text
.global _start
_start:
movb $0, %rdi
movb data_items(,%rdi,1),%al
movb %al, %bl

start_loop:
cmpb $-1, %al
je loop_exit
inc %edi
movb data_items(,%rdi,1), %al
cmpb %bl, %al
jg start_loop   # if al > bl we have not found the new minimum and we can start again

movb %al, %bl
jmp start_loop
loop_exit:

movb $1, %al
int $0x80

But this code is still wrong.

Another problem is the sign of numbers. If you want to consider data_items as an array of signed ints, 222 will be -34. If you consider data_items as unsigned ints, -1 will be 255. Thus what you could do is replacing jg start_loop with ja start_loop

data_items:
.byte 3,67,34,222,45,75,54,34,44,33,22,11,66,-1
.section .text
.global _start
_start:
movb $0, %rdi
movb data_items(,%rdi,1),%al
movb %al, %bl

start_loop:
cmpb $-1, %al
je loop_exit
inc %edi
movb data_items(,%rdi,1), %al
cmpb %bl, %al
ja start_loop   # if al > bl we have not found the new minimum and we can start again

movb %al, %bl
jmp start_loop
loop_exit:

movb $1, %al
int $0x80

On my machine, changing a bit your code, I get correctly 3 as exit code.

P.S. I still wonder how movb $0, %rdi might work...

This is the version which I run on my x86_64 box (I assume you are on x86_64 since you used %rdi)

/* min.S */
/* Compile with gcc -nostdlib min.S */
#include <syscall.h>

data_items:
.byte 3,67,34,222,45,75,54,34,44,33,22,11,66,-1
.section .text
.global _start
_start:
movq $0, %rdi
leaq data_items(%rip),%rdi
movb (%rdi), %al
movb %al, %bl

start_loop:
cmpb $-1, %al
je loop_exit
inc %rdi
movb (%rdi), %al
cmpb %bl, %al
ja start_loop   # if al > bl we have not found the new minimum and we can start again

movb %al, %bl
jmp start_loop
loop_exit:

movq $SYS_exit, %rax
movzx %bl, %rdi
syscall

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1