我知道,如果设置了标志标志,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标志。
答案 0 :(得分:1)
您发布的代码是正确的;我不知道您为什么首先想到了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