1

So, we're beginning to do small things in x86 but I can't grasp it at all. We have this:

  .Data
  frequency DW 0, 260, 300, 330, 350, 390, 440, 500, 520, 590, 660, 700

I have to iterate through it, seems simple for me, but:

  mov EAX, frequency  
  mov ECX, 0  // as a counter

Isn't correct, am I right? I was thinking about moving to EAX the address of frequency, but then again doesn't seem right to me.
Anyone can help me know how to do a simple [ if != 700 ] loop?
Don't really care about the loop, just want to know how to get the elements on "frequency" into a register and then keep getting the next one.

Sep Roland
  • 20,265
  • 3
  • 36
  • 58
Baalth
  • 13
  • 3

2 Answers2

0

You're right on the first one.

mov EAX, frequency gets the address for the first element.
mov dx, [eax] gets an element from the array.
add eax, 2 moves to the next element.

Sep Roland
  • 20,265
  • 3
  • 36
  • 58
0

You will have to assume that these values are stored contiguously in memory. Then you obtain a pointer to (address of) the first one, and iterate through them by continuously incrementing that pointer by the size of each element.

To know when to stop iterating (i.e., for the loop termination condition), you can either use a counter (because you know that there are a constant 12 elements), or you can check the value to see if it is 700 (then you know you're at the end).

Here is an example that uses a counter:

    mov  ecx, 0                  ; initialize counter
    mov  edx, OFFSET frequency   ; get address of the first element
DoLoop:
    mov  eax, DWORD PTR [edx]    ; get value of the element
    ...                          ; do something with that value, now in the EAX register
    inc  ecx                     ; increment counter by one
    add  edx, 2                  ; increment pointer by size of an element
    cmp  ecx, 12                 ; compare counter against 12 (total number of elements)
    jl   DoLoop                  ; keep looping while less than 12

There are multiple ways to write this loop, some perhaps slightly more optimal than the above code, but that should give you the idea.

If you just want to do a simple "if x != 700" loop, then it is as simple as:

cmp  X, 700       ; where X is some register or memory location that you want to test
jne  BranchLabel  ; where 'BranchLabel' is the label to jump to if X != 700

In general, on x86, you will do a conditional branch using a CMP instruction to set the flags, followed by a Jcc instruction that actually does the branching (where cc is a condition code that specifies how the flags are to be tested).

However, you do not have to use a CMP instruction. There are a bunch of other instructions that set flags, including TEST and nearly all of the arithmetic and bitwise instructions (e.g., ADD, SUB, XOR, etc.) If the flags have already been set, then you can just do the Jcc directly. There is no need for a redundant comparison!

Cody Gray
  • 222,280
  • 47
  • 466
  • 543
  • 3
    Perhaps a good idea to actually read a *word* in stead of a *dword* since you increment the pointer by 2 to get to the next element. – Sep Roland Dec 04 '16 at 18:21
  • Whether it's a good idea or just a valid idea depends upon your specific target architecture. In many cases, on modern processors, this will actually be faster. But you're right, it would certainly have been *more clear* if I'd read a word-sized value. – Cody Gray Dec 05 '16 at 12:10
  • `movzx eax, word ptr [edx]` isn't slower on current CPUs (running as a pure load in the load port), and avoids any risk of a cache-line split. It only costs one extra byte of machine-code size vs. a dword `mov`. If you mean `mov ax, [edx]` might be slower, then yes, [partial registers are generally to be avoided](https://stackoverflow.com/questions/41573502/why-doesnt-gcc-use-partial-registers) when you easily can. P5 Pentium had slow movzx for some reason, but that's ancient history. Modern CPUs simply handle it in a load port, no separate ALU uop required. – Peter Cordes May 21 '21 at 17:54