# [nasm] Simple Array Reading Program

1. Nov 4, 2012

### twoski

1. The problem statement, all variables and given/known data

Write a program in nasm which will read through a 5x5 matrix and print the largest value.

3. The attempt at a solution

I ran this through a debugger and for some reason $edi reaches 19 and sets$esi to 0. Which is weird since the value at [eax + edi * 4] should be 4, not 0.

My output code is wonky too, i could use some help with that.

Code (Text):

segment .data

matrix dd 1,1,1,1,1, \
2,2,2,2,2, \
3,3,3,3,3, \
4,4,4,4,4, \
5,5,5,5,5

segment .bss

empty resb 4
count resb 4

segment .text

global _start

_start:

mov eax, matrix
call FindGreatest

FindGreatest:

mov esi, [empty]
mov edi, [count]
mov edi, 0
jmp Switch

Comparison:

inc edi
cmp esi, [eax + edi * 4] ; compare stored number with new number
jg Switch ; it's bigger so replace it
cmp edi, 25 ; check if we are out of bounds
jle Comparison ; start over again if we can
mov eax, esi
add eax, 30h ; is this the proper way to convert???
mov esi, eax
jmp Print ; print the value now that we have traversed the matrix

Switch:

mov esi, [eax + edi * 4] ; we found a higher number
jmp Comparison

Print:

mov edx, 4
mov ecx, esi ; we are outputting the stored digit as text
mov ebx, 1
mov eax, 4 ; output with stdio
int 0x80
jmp exit

exit:

mov eax, 1
xor ebx, ebx
int 0x80

Last edited: Nov 5, 2012
2. Nov 5, 2012

### Staff: Mentor

You have a couple of things that seem weird to me, that might be causing problems for you. First, your count label isn't initialized at the start. When your code starts, you move the first matrix value into eax, and then call FindGreatest. You then move the address of empty to esi and the address of count into edi. You then overwrite edi with 0, so what was the point of the previous instruction?

Second, why do you call FindGreatest? If you deleted the line with "call FindGreatest" you code would behave exactly the same.

Third, the last instruction in FindGreatest branches to Switch. This causes the value that was in esi (the address of empty) to be overwritten by a new value. The comment here is misleading, since it says you have found a larger number.

Fourth, you have a variable named count that you never use. Instead you have hard-coded 25 (the count of elements in matrix) in the Comparison section.

The good news is that you are using a debugger, which is an important tool when you are writing assembly code. A useful exercise for you is to hand-simulate what you think your code is doing for two or three iterations, and then use your debugger to verify that your predictions were correct.

3. Nov 5, 2012

### twoski

Thanks for your reply! I'm noticing a lot of silly errors now, i guess it's good to get a good night's sleep then re-read your code.

I think my program can work fine without the two variables i am using. 'count' isn't needed, nor is 'empty'.

I did some tidying up, my output code is still wonky at best. Is "mov ecx esi" a valid instruction?

Code (Text):
mov eax, esi
mov esi, eax
jmp Print
Is this the correct way to convert decimal to a printable character? And would it work for numbers with >1 digit?

4. Nov 5, 2012

### Staff: Mentor

I believe so.
This is the correct way to convert a single decimal digit to the corresponding digit character. For example, if 4 is copied to eax from esi, the next instruction adds 30h, resulting in 34h or 5210. This is the ASCII code for the '4' character.
No, it works only with single-digit number.

Your Print routine uses interrupt 0x80, which suggests to me that your OS is Linux, since that's not a DOS interrupt function. I don't know what functions are available with this interrupt, so you're on your own there. If you want to print 35, for example, you will need a loop that figures out what digit is in the 10's place and what digit is in the 1's place, and then display each digit as a character.

5. Nov 5, 2012

### rcgldr

Yes, but it would be "mov ecx, esi".

Some optional changes you could make to the code:

You can use this to define an equate for the number of entries in matrix:

Code (Text):

matrix  dd    1,1,1,1,1, \
2,2,2,2,2, \
3,3,3,3,3, \
4,4,4,4,4, \
5,5,5,5,5

7. Nov 5, 2012

### Staff: Mentor

That's not the way cmp works.

cmp A, B does a subtraction of A - B. Since 1 - (eax + 6*4) is apparently negative (I don't know the value of eax), the jg instruction doesn't execute. jl would, though.

I'm a little rusty on this, but I believe that if A < B, SF (sign flag) in the flags register gets set. If the two values happen to be equal, ZF (zero flag) gets set. The conditional jump instructions use the flags register to determine whether the jump should be taken.

8. Nov 6, 2012

### rcgldr

Code (Text):

cmp     esi, [eax + edi * 4]
jg      Switch

cmp works similar to subtract: the comparson is based on esi - [eax + edi*4] . You want to branch when esi is less than the matrix value (which means the matrix value is > esi), so what you want here is:

Code (Text):

cmp     esi, [eax + edi * 4]
jl      Switch

If these were unsigned numbers then you would use jb Switch instead (jump if borrow set).

Also look at my previous post for an alternate way to define matrixlen so that it's based on the actual size of matrix.

Last edited: Nov 6, 2012