Как найти нечетное целое число на ассемблере? - PullRequest
0 голосов
/ 22 октября 2018

Напишите процедуру на ассемблере, чтобы умножить два целых числа на удвоение и деление на два.Вот псевдокод для умножения A и B с использованием этого подхода.

Multiply A and B and store result in C:
C = 0 ; Initialize to 0
while B is not equal to 0:
if B is odd then C = C+A ; Add copy of A (even number left)
A = 2*A ; Can be done quickly by shifting left
B = B/2 ; Can be done quickly by shifting right

Я уже много сделал, как бы я использовал shl для проверки на нечетное целое число?

Ответы [ 2 ]

0 голосов
/ 22 октября 2018

для x86_64 вы можете использовать shr для проверки нечетности и нуля ...

Например, вот так:

Для сборки и тестирования в Отладчик Я использовал команды (на 64-битной Linux):

nasm -f elf64 m.asm -l m.lst -w+all; ld -b elf64-x86-64 -o m m.o
edb --run ./m

source:

    segment .text

mulByBits:
; input: 2x uint32_t in edi, esi (System V AMD64 ABI calling convention)
; output: uint64_t in rax
; modifies also: rcx
    xor     eax, eax            ; rax = 0 "C"
    mov     edi, edi            ; clear upper 32b of input "A" (extend to 64b)
.mulLoop:
    lea     rcx, [rax + rdi]    ; rcx = C + A (new C in case B is odd)
    add     rdi, rdi            ; A *= 2 (for next loop)
    shr     esi, 1              ; B >>= 1 (sets ZF and CF)
    cmovc   rax, rcx            ; if B was odd, update the sum to new C
    jnz     .mulLoop            ; repeat until B is zero
    ret

global _start
_start:     ; run some hardcoded simple tests, verify in debugger
    mov     edi, 143254         ; "normal" values test
    mov     esi, 43526
    call    mulByBits
    mov     rbx, 6235273604     ; expected result, compare with rax

    mov     edi, 0
    mov     esi, 0
    call    mulByBits
    mov     rbx, 0

    mov     edi, 43257432
    mov     esi, 0
    call    mulByBits
    mov     rbx, 0

    mov     edi, 0
    mov     esi, 432543
    call    mulByBits
    mov     rbx, 0

    mov     edi, 3276547234
    mov     esi, 1
    call    mulByBits
    mov     rbx, 3276547234

    mov     edi, 1
    mov     esi, 3276547234
    call    mulByBits
    mov     rbx, 3276547234

    mov     edi, ~0             ; UINT_MAX * UINT_MAX
    mov     esi, ~0
    call    mulByBits
    mov     rbx, 0xFFFFFFFE00000001

    mov     rdi, 0xE00000004    ; garbage in upper 32 bits of inputs
    mov     rsi, 0xE00000004    ; should be multiplied as 4*4
    call    mulByBits
    mov     rbx, 0x10

    ; exit back to linux
    mov     eax, 60
    xor     edi, edi
    syscall

Добавление - наиболее эффективный способ сдвига влево на 1 на большинстве процессоров;add same,same может работать на большем количестве исполнительных портов, чем shl rdi,1 (https://agner.org/optimize),, что позволяет больше параллелизма на уровне команд для потенциально лучшей пропускной способности цикла.

0 голосов
/ 22 октября 2018

можно использовать инструкцию 'shr' 100

mov al, 0x10010010b
shr al, 1      ;CF = 0   even

mov al, 0x10010011b
shr al, 1      ;CF = 1   odd

jnb __lable    ;jump if CF = 0
or
jb  __lable    ;jump if CF = 1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...