Page 1 of 1

loop instruction zeros cx for some reason

Posted: Wed Jun 03, 2009 10:05 pm
by alethiophile
I have a doubly nested loop that I use to search the FAT root directory for a filename in a bootloader. The code follows:

Code: Select all

.ff_search_loop:
        mov     si,     dx              ;; beginning of string
        mov     di,     bx              ;; entry to search
        push    cx                      ;; save loop counter
        mov     cx,     11              ;; length of filename
.ff_strcmp_loop:
        cmpsb                           ;; compare bytes
        jne     .ff_next                ;; if unequal, try next entry
        loop    .ff_strcmp_loop
        jmp     ff_search_done          ;; if loop finishes, then it matches
.ff_next:
        add     bx,     32              ;; try next entry (32-byte entries)
        pop     cx                      ;; restore original loop counter
        loop    .ff_search_loop         ;; if loop finishes, then not found -- this is the problem

ff_not_found:
        mov     word [ebp - 4], 0xffff  ;; return val: not found
        jmp     ff_done

ff_search_done:
        mov     word [ebp - 4], bx      ;; save entry offset

ff_done:
For some reason, the second loop instruction zeros cx, and hence does not loop, and falls through to the not_found code. Bochs register dump immediately before the instruction:

Code: Select all

eax: 0x00000280 640
ecx: 0x00000200 512
edx: 0x00008f1b 36635
ebx: 0x00009ea0 40608
esp: 0x00009be5 39909
ebp: 0x00009bf9 39929
esi: 0x00008f1c 36636
edi: 0x00009e81 40577
eip: 0x00008d98
eflags 0x00000286
id vip vif ac vm rf nt IOPL=0 of df IF tf SF zf af PF cf
Immediately after:

Code: Select all

eax: 0x00000280 640
ecx: 0x00000000 0
edx: 0x00008f1b 36635
ebx: 0x0000de80 56960
esp: 0x00009be5 39909
ebp: 0x00009bf9 39929
esi: 0x00008f1c 36636
edi: 0x0000de61 56929
eip: 0x00008d9a
eflags 0x00000282
id vip vif ac vm rf nt IOPL=0 of df IF tf SF zf af pf cf
The instruction also messes with the values of bx and di, which are the variables that are changed within the outer loop. Does anyone know why this is happening?

Edit:
Note that it also clears the parity flag; is that relevant?

Re: loop instruction zeros cx for some reason

Posted: Wed Jun 03, 2009 10:31 pm
by Firestryke31
loop decrements cx and jumps if not zero (IIRC) cmpsb compares ds:si to es:di and increments both (once again, IIRC).

I've found this site very useful for ASM programming.

Re: loop instruction zeros cx for some reason

Posted: Wed Jun 03, 2009 10:32 pm
by bewing
How do you know it's not looping? It sounds like it is looping just fine and simply not finding the specified filename.

Re: loop instruction zeros cx for some reason

Posted: Wed Jun 03, 2009 10:33 pm
by mintie
Why not just do a repe cmpsb instead of looping around a cmpsb? Something like this should work:

Code: Select all

...
.ff_strcmp_loop:
mov cx, 11
repe cmpsb
jz ff_search_done
...

Re: loop instruction zeros cx for some reason

Posted: Wed Jun 03, 2009 10:35 pm
by alethiophile
OK, there it is. When I type 'n' in bochs, it apparently skips over the entirety of a loop, as it does a function. Seems a dumb behavior. Thanks for the help. Also, I am currently using a double loop because it's simpler; I may switch to a repe at some point, but not now.

Re: loop instruction zeros cx for some reason

Posted: Wed Jun 03, 2009 10:41 pm
by Troy Martin
alethiophile wrote:because it's simpler
Ummm, no, it's really not. One line versus five or six. One line needs no labels, five or more needs multiple. Also takes up an extra 5-10 bytes that could be used for a better bootloader.

Re: loop instruction zeros cx for some reason

Posted: Thu Jun 04, 2009 8:50 pm
by alethiophile
OK, because when I first wrote this code, I didn't really understand rep, and since I haven't gotten around to changing it. I'll probably do that now.

Re: loop instruction zeros cx for some reason

Posted: Thu Jun 04, 2009 11:24 pm
by egos
What strange values of esp and ebp you have. Align stack pointer to 2 or 4 bytes. Why are you using ebp register, but not bp?

Re: loop instruction zeros cx for some reason

Posted: Thu Jun 11, 2009 4:52 am
by Ready4Dis
Also, you are NOT restoring CX to it's original value, and are trashing your stack. Look at your code path if you do a jump to ff_search_done, you never POP CX back to its original value, which means you've left 2-bytes on the stack, that will end up being popped into another variable unkowingly (leaving a nice bug to track down). Using REP will help fix this problem, but you need to be careful with push/pop. These problems tend to show up later on, after you're done testing it by itself and implement it into your other code.