arraysassemblyx86nasm

Why does loading EAX from a byte array not compare equal to the literal I expected?


I am new to assembly and was trying to work with an array. However, I was geting caught when try to compare the array value to a constant stored in a register.

From the following code I was expecting the program to jump after comparison because the value in the array seems to match the literal in esi. My code is as follows.

global _start
section .data
         yay: db "It Worked!",0xA
         array1: db 1, 2, 3, 4
 section .bss

section .text
         _start:
                  mov eax, [array1 + 1]
                  mov esi, 2
                  cmp eax, esi
                  je .equal
                  jmp _done
 
          .equal:
                  mov eax, 4
                  mov ebx, 0
                  mov ecx, yay
                  mov edx, 11
                  int 0x80
                  jmp _done
 
          _done:
                  mov eax, 1
                  mov ebx, 0
                  int 0x80

Any advice as to mistakes in my code are greatly appreciated too!


Solution

  • The reason your code is not properly loading the value located at the first index of your array into EAX is because of what an array is in assembly. In assembly, when you define an "array" you are simply placing data into memory. While this might seem obvious, it also means that there is NOT a separator between elements (A "string" is also an array). This means that when you do MOV EAX, [ARRAY1 + 1] without specifying the size of the operation, nasm looks at the context of the instruction to defer the size. Because you are using a 32-bit register, the size is defaulted to a DWORD. This means that the instruction will load 32 bits (4 bytes) from your array starting at [ARRAY1 + 1]. To prevent this, you need to specify the size of your operation as a byte by doing MOVZX EAX, BYTE [ARRAY1 + 1]. You need to use MOVZX to fill the rest of the register with zeros.

    General Tips

    The first thing that sticks out to me about your code is the usage of JMP right before the label you are jumping too. This is unnecessary because execution will just continue into a label. This is because labels are not "functions," rather just markers that represent memory addresses. They do not exist in the assembled program. Secondly, while not major, instead of doing MOV EAX, 0, it is slightly faster to execute XOR EAX, EAX. Finaly, you have an empty BSS section, this is not needed for the linker and can just be left out (at least for ld).