Почему прыгать подписанная инструкция работает противоположно - PullRequest
0 голосов
/ 16 мая 2019

Я знаю, что инструкция js - это переход, если установлен флаг знака.Я хочу сделать процедуру, которая сравнивает каждый элемент массива и подсчитывает, если разность двух элементов меньше 5.

CountMatch proc
    push ebp
    mov ebp, esp
    push esi
    push edi
    mov ecx, [ebp + 12]; length of arrays
    mov esi, [ebp + 20]; address of array1
    mov edi, [ebp + 16]; address of array2

CHKMATCH :
    mov eax, [esi]
    sub eax, [edi]
    jns ELSEloop    ;this line is problem
    neg eax
    cmp eax,5
    ja CONTINUE
    inc count
    jmp CONTINUE
ELSEloop:
    cmp eax,5
    ja CONTINUE
    inc count

CONTINUE :
    add esi, 4
    add edi, 4
    loop CHKMATCH

    mov eax, count
    call writeint
    call crlf
    pop edi
    pop esi
    pop ebp
    ret 16
CountMatch endp

Когда программа выполняет цикл CHKMATCH, она может работать правильнопотому что, если разница отрицательна, устанавливается флаг знака.Так что его можно отрицать и сравнивать с 5. Но это не работает, поэтому я изменил его на jns.В режиме отладки мне не удалось найти флаг знака, но я вижу флаг PL.

1 Ответ

1 голос
/ 17 мая 2019

Код, который вы разместили, верен; и я не знаю, почему вы думали, что вы хотели js во-первых.

Обратите внимание, что было бы проще сделать это:

    mov eax, [esi]
    sub eax, [edi]      ;eax = difference maybe (if it didn't overflow)
    jns NOT_NEGATIVE    ;If difference is not negative (sign flag not set), don't negate
    neg eax             ;Difference was negative, so negate it to make it positive
NOT_NEGATIVE:
    cmp eax,5
    ja CONTINUE
    inc count
CONTINUE:

Также; Вы сказали (в описании вопроса) «считает, если разность двух элементов меньше 5», а код действительно «считает, если разность двух элементов меньше или равна 5». В зависимости от того, что вы на самом деле хотите, вам может понадобиться jae CONTINUE (или его синоним jnb CONTINUE).

Наконец, возможно, быстрее сохранить count в регистре (например, возможно, в edx); и если вы сделаете это, то, вероятно, быстрее избежать ветвления с помощью такого трюка, как:

NOT_NEGATIVE:
    cmp eax,5          ;Set carry flag if difference < 5
    adc edx,0          ;Add carry flag to count
CONTINUE:

В этом случае вы также можете избавиться от mov eax,count, поменяв местами eax и edx; как может быть:

CountMatch proc
    push ebp
    mov ebp, esp
    push esi
    push edi
    mov ecx, [ebp + 12]   ; length of arrays
    mov esi, [ebp + 20]   ; address of array1
    mov edi, [ebp + 16]   ; address of array2
    xor eax,eax           ; eax = count = 0

CHKMATCH :
    mov edx, [esi]
    sub edx, [edi]      ;edx = difference maybe (if it didn't overflow)
    jns NOT_NEGATIVE    ;If difference is not negative (sign flag not set), don't negate
    neg edx             ;Difference was negative, so negate it to make it positive
NOT_NEGATIVE:
    cmp edx,5          ;Set carry flag if difference < 5
    adc eax,0          ;Add carry flag to count
CONTINUE:
    add esi, 4
    add edi, 4
    loop CHKMATCH

    ; eax = count already

    call writeint
    call crlf
    pop edi
    pop esi
    pop ebp
    ret 16
CountMatch endp
...