问题
So I'm trying to separate an octet by parity and I don't quite understand how the conditional jumps work(I tried it separately and I don't understand how it works it)
Here is what I came up with:
bits 32
global start
extern exit,printf
import exit msvcrt.dll
import printf msvcrt.dll
segment data use32 class=data
s db '1', '2', '3', '4','5','7','8','9' ; declararea sirului initial s
l equ $-s ; stabilirea lungimea sirului initial l
d1 times l db 0
d2 times 1 db 0
format db "%s", 0
segment code use32 class=code
start:
mov ecx, l
mov esi, 0
jecxz Sfarsit
Repeta:
;loop so it gets all the elements from s
mov al, [s+esi]
mov bl,al
sub bl,'0'
cmp bl,2; if is even adds it to d1
JP et2
mov [d1+esi], al
inc esi
et2:
mov bl,al
sub bl,'0'
cmp bl,2; if is odd adds it to d2
JP et1
mov [d2+esi], al
inc esi
et1:
loop Repeta
Sfarsit: ;terminarea programului
;Daca dorim si afisarea sirului d, avem urmatoarele:
push dword d1 ; punem parametrii pe stiva de la dreapta la stanga
push dword format
call [printf] ;apelam functia printf
add esp, 4 * 2 ; eliberam parametrii de pe stiva
; exit(0)
push dword d2 ; punem parametrii pe stiva de la dreapta la stanga
push dword format
call [printf] ;apelam functia printf
add esp, 4 * 2 ; eliberam parametrii de pe stiva
; exit(0)
push dword 0 ; push the parameter for exit onto the stack
call [exit] ; call exit to terminate the program
I think the problem is the JP but I'm not completely sure.
回答1:
cmp bl,2; if is even adds it to d1
JP et2
cmp in this case does temp = bl - 2 and throws away the result, but keeps the flags affected (same way as sub bl,2 would affect them).
And jp is "jump parity", which means it will jump when PF=1, it has also alias jpe or "jump when even".
But that's about bit-parity of the low 8 bits of result, i.e. it counts number of "1" values in low 8 bits of result and sets PF=1 when there's even number of ones. As you use only 8 bits in the arithmetic flag setting instruction (cmp), the whole result is used to calculate PF, but if you would do for example cmp ebx,2, it would have same result in PF, as only 8 bits of result are used to count ones.
In your case the values processed (in binary):
bl temp (low 8b) PF
0001 (1) 11111111 (-1) 1 (8 mod 2 = 0)
0010 (2) 00000000 (0) 1 (0 mod 2 = 0)
0011 (3) 00000001 (1) 0 (1 mod 2 = 1)
0100 (4) 00000010 (2) 0 (1 mod 2 = 1)
0101 (5) 00000011 (3) 1 (2 mod 2 = 0)
0111 (7) 00000101 (5) 1 (2 mod 2 = 0)
1000 (8) 00000110 (6) 1 (2 mod 2 = 0)
1001 (9) 00000111 (7) 0 (3 mod 2 = 1)
So bl values 1, 2, 5, 7, 8 will take jp jump.
If you want to test bl if the value is even (bl mod 2 = 0), then you need:
test bl,1 ; mask-out all bit except the lowest one
jz even_value ; when lowest bit is zero, value is even
The test instruction does temp = bl AND 00000001, and throws away result (temp), keeps only flags. Binary values are even, when their lowest digit (bit) is zero, because that one has value 20 = 1, so that's the one which makes odd values possible. When you bit-wise mask the original value against 00000001, you keep only the lowest bit, so jz "jump zero" will happen when that lowest bit was zero -> value was even.
also probably some more problems you will encounter:
d1 times l db 0
d2 times 1 db 0 ; probably "times l db 0" meant?
And you wanted to split values into d1 / d2 when they are even odd?
But you are using the same index esi, so if you will fix your test, and your "store value into" logic, you will split the values into two arrays:
d1: '1', 0, '3', 0, '5', '7', 0, '9'
d2: 0, '2', 0, '4', 0, 0, '8', 0
And your current code will store only values which set PF=0, but into both arrays, as both your branches have identical calculation.
To get the arrays as described above (with odd/even values, on their original index) you can do:
mov edi,d1 ; target array ptr for odd values
mov edx,d2 ; target array ptr for even values
test al,1 ; test if al has even value
; you can test directly the ASCII digit, '0' = 0x30 = even
cmovz edi,edx ; edi = target array ptr
mov [edi+esi],al ; store AL into desired array
... and I will rather not even check code below that loop, but I think you should execute it in debugger, and single-step over each instruction to see, what it does (very likely NOT, what you did want/expect).
来源:https://stackoverflow.com/questions/47372252/parity-of-a-number-assembly