8

I've a problem in assembly language that i got to access element of an array... suppose an array contains weeks day... like sun,mon,tues,wed.... i have to access 2nd index of the array... How can I do this?

İsmet Alkan
  • 5,361
  • 3
  • 41
  • 64
user337099
  • 91
  • 1
  • 2
  • 3

1 Answers1

16

Indexing in assembly is basically the same as C/C++ except for one difference: you have to know the size of your data elements.

For example, to loop through an array of bytes (or characters in a string) in assembly, you could do the following:

mov eax, 0
mov ecx, 0

loop_start:
  cmp ecx, ARRAY_LENGTH
  jge loop_end

  add eax, BYTE PTR myArray[ecx]

  add ecx, 1
  jmp loop_start
loop_end:

As you can see, the array is looped through one element at a time by incrementing ecx (which I'm using as a counter). Each element is added to eax which contains the sum at the end of the loop. Notice I had to add "BYTE PTR" when referencing the array to tell the assembler what type of data I'm using.

Now take a look at this code which does the same thing for DWORD data (4 bytes):

mov eax, 0
mov ecx, 0

loop_start:
  cmp ecx, ARRAY_LENGTH
  jge loop_end

  add eax, myArray[ecx*4]

  add ecx, 1
  jmp loop_start
loop_end:

Only two things changed: I no longer needed to use "BYTE PTR" here because, unless told otherwise, the assembler assumes you are using 32-bit data types on a 32-bit machine; I also needed to change the index of the array to "ecx*4" because each element in the array is 4 bytes long. Most data types used on 32-bit machines are 32 bits in size so the later example will be more common.

To answer your specific question, here is one way to loop through an array of strings and display them:

.data
  sunday    db "Sun",0
  monday    db "Mon",0
  tuesday   db "Tues",0
  wednesday db "Wed",0
  thursday  db "Thurs",0
  friday    db "Fri",0
  saturday  db "Sat",0

  daysOfWeek dd OFFSET sunday, OFFSET monday, OFFSET tuesday OFFSET wednesday
             dd OFFSET thursday, OFFSET friday, OFFSET saturday

.code
mov ecx, 0

loop_start:
  cmp ecx, 7
  jge loop_end

  mov eax, daysOfWeek[ecx*4]
  ; eax now contains the pointer to the
  ; next element in the array of days

  add ecx, 1
  jmp loop_start
loop_end:

Because pointers on a 32-bit machine are 32 bits wide, treat them like DWORDs as in the second example.

Sparafusile
  • 4,696
  • 7
  • 34
  • 57
  • btw it's nitpicking but you could simplify the assembly by counting downward instead of upward: `mov ecx, ARRAY_LENGTH; loop_start: add eax, BYTE PTR myArray[ecx]; dec ecx; jnz loop_start` – galois Nov 13 '16 at 06:44
  • 1
    I didn't know how he was going to use the strings. If he was going to output them to the screen, it would be odd to see them in reverse order. Premature optimization is the root of all evil. – Sparafusile Nov 13 '16 at 17:49
  • `add eax, BYTE PTR myArray[ecx]` won't assemble. You need a separate `movzx` or `movsx` instruction to zero- or sign-extend before you can add to a 32-bit register. Also, [the idiomatic loop structure in asm has the conditional branch at the bottom]([Why are loops always compiled into "do...while" style (tail jump)?](https://stackoverflow.com/q/47783926), so these examples are painful to look at. – Peter Cordes Jun 23 '18 at 03:55
  • *unless told otherwise, the assembler assumes you are using 32-bit data types on a 32-bit machine* No, the assembler infers the operand size from a register. Or with MASM, also from the db/dw/dd/dq in `label dd 1,2,3` if you're using a symbol name in your addressing mode. – Peter Cordes Jun 23 '18 at 03:56
  • @Peter Cordes so "add eax, memory_address" is the same as "add eax, BYTE PTR memory_address" because I used the same register? Obviously not. My point was, and I don't think it was unclear, that you don't need to specify the size of the operand in my example when it's 32 bits on a 32 bit machine. However you can clearly use a 16 or 8 bit operand by explicitly stating its size. – Sparafusile Jun 25 '18 at 15:41
  • If you want 8-bit operand size, you have to write `add al, BYTE PTR memory_address`. You *can't* use a 32-bit register as a destination unless the memory operand is also 32 bits wide, except with movzx/movsx, like `movzx edx, BYTE PTR memory_address` / `add eax, edx`. The difference is whether your total wraps at 256 or at 2^32. – Peter Cordes Jun 25 '18 at 16:05