This question already has an answer here:
-
Parity of a number (Assembly 8086)
5 answers
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.
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).