dareesome
dareesome

Reputation: 133

How do I properly compare an element in an array with a variable in nasm assembly x86?

Im a beginner at assembly and Im making a program that is going to take the value in a variable num and seeing if that number is in an array, it will print "That number is in the array" if not it will print something else. But it always prints, "The number is not in the array". Why?

section .text
    global _start
    
_start:
    mov eax, [numArray]
    mov ecx, 3 ;How many times Num will loop
    
Num:
    cmp [num], eax ;compare num to eax
    je inArray ;If equal go to inArray message
    dec ecx ;decrement ecx
    inc eax ;move to next element
    jz notIn ;If counter = 0 and a match still has not been found goto notIn
    jnz Num ;Else go back to Num
    
inArray: ;Print msg1
    mov eax, 4
    mov ebx, 1
    mov ecx, msg1
    mov edx, len1
    int 0x80
    
    jmp _exit
    
notIn: ;Print msg2
    mov eax, 4
    mov ebx, 1
    mov ecx, msg2
    mov edx, len2
    int 0x80
    
    jmp _exit
    
_exit: ;exit program
    mov eax, 1
    int 0x80
    
section .data
    num db 1
    numArray db 1, 2, 3
    
    msg1 db 'That is in the array!'
    len1 equ $-msg1
    
    msg2 db 'That is not in the array'
    len2 equ $-msg2

Upvotes: 0

Views: 709

Answers (1)

Kai Burghardt
Kai Burghardt

Reputation: 1572

Some basic things:

mov eax, [data]

means, retrieve the contents indicated by the address data and store them in eax. This instruction retrieves a 32-bit quantity, because you have specified a 32-bit destination. If you want to retrieve just one Byte, you will need to specify an 8-bit destination:

mov al, [data]

Furthermore, if you want to load the address of a variable (a label), you simply write

mov rax, data

Confer point 5: Confusing value and address of a variable. For an address, a pointer, you almost always use a 64‑bit register (in 64‑bit mode), confer 10.5 Addresses and pointers in 64-bit mode.

lea rax, [data]

does effectively the same, but as you can see different notation, different instruction, thus different code.


You usually use string instructions for that kind of task. Unlike in high-level programming languages, “string” means any kind of continuous data, not just character strings.

global _start
bits 64
default rel

; ### constants ################################################
sys_exit:            equ            1

; ### intialized data ##########################################
section .data

data:
    db 42, -6, 13, -7, 99, 2
data_size:           equ     $ - data

; ### executable code section ##################################
section .text

_start:
    xor ebx, ebx                        ; ebx ≔ 0
    
    mov ecx, data_size                  ; exc ≔ count
    mov rdi, data                       ; rdi ≔ @data
    mov eax, 99                         ; the number to find
    
    repne scasb                         ; scan string Byte
    
    ; as it customary for program exit status: 0 means
    ; successful, and any non-zero value indicates an error
    setnz bl                            ; bl ≔ ¬ZF
exit:
    mov eax, sys_exit                   ; request number
    int 0x80

; vim: set ft=nasm:

cld (“forward” direction) has been omitted because the used ABI says it must be cleared upon process initialization (and function entry and return).

scasb retrieves a Byte from the location indicated by the value in rdi, compares it to the contents in al, sets the ZF according to the result, increments rdi (depends on DF) and decrements rcx. All of that in one instruction. The repne prefix simply means, while the ZF is clear and ecx has not hit 0 yet.

Upvotes: 1

Related Questions