数字的奇偶性(汇编)

时间:2017-11-18 23:39:17

标签: assembly x86 nasm

所以我试图通过奇偶校验来分隔一个八位字节,我不太明白条件跳转是如何工作的(我单独尝试它并且我不明白它是如何工作的)

以下是我提出的建议:

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

我认为问题是JP,但我并不完全确定。

1 个答案:

答案 0 :(得分:2)

    cmp bl,2; if is even adds it to d1
    JP et2
在这种情况下,

cmp执行temp = bl - 2并抛弃结果,但会阻止标记受影响(与sub bl,2相同的方式会影响它们)。

并且jp是"跳转奇偶校验",这意味着它将在PF = 1时跳转,它还具有别名jpe或"甚至"

但这是关于低8位结果的位奇偶校验,即它计算" 1"结果的低8位值,当有偶数时,设置PF = 1。由于您在算术标志设置指令(cmp)中仅使用了8位,因此整个结果用于计算PF,但如果您执行cmp ebx,2,则在PF中会产生相同的结果,因为只有8位结果用于计数。

在您的情况下处理的值(二进制):

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)

所以bl值1,2,5,7,8将会jp跳跃。

如果你想测试bl,如果值是偶数(bl mod 2 = 0),那么你需要:

    test bl,1           ; mask-out all bit except the lowest one
    jz   even_value     ; when lowest bit is zero, value is even

test指令执行temp = bl AND 00000001,抛出结果(temp),只保留标志。二进制值是偶数,当它们的最低位(位)为零时,因为它具有值2 0 = 1,所以这是使奇数值成为可能的值。当您按原样对00000001屏蔽原始值时,只保留最低位,因此jz"跳零和#34;当最低位为零时将发生 - >价值是均匀的。

您可能会遇到更多问题:

d1 times l db 0
d2 times 1 db 0    ; probably "times l db 0" meant?

你想在奇怪的时候将价值分成d1 / d2吗? 但是你使用相同的索引esi,所以如果你要修改你的测试,你的"存储价值进入"逻辑,您将值分成两个数组:

d1:    '1', 0, '3', 0, '5', '7', 0, '9'
d2:    0, '2', 0, '4', 0, 0, '8', 0

您当前的代码只会存储设置PF = 0的值,但会存储到两个数组中,因为两个分支都有相同的计算。

要获得如上所述的数组(奇数/偶数值,在原始索引上),您可以这样做:

    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

...而且我甚至不会检查该循环下面的代码,但我认为你应该在调试器中执行它,并在每条指令上单步执行以查看它的作用(很可能不是,你想要的是什么) /预期)。