编写一种汇编语言过程,以将两个整数乘以两倍和减半来相乘。这是使用这种方法将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测试奇数整数?
答案 0 :(得分:1)
它可以使用'shr
'指令;
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
答案 1 :(得分:0)
对于x86_64,您可以同时使用shr
进行奇数测试和零测试...
例如:
要在debugger中进行构建和测试,我使用了命令(在64b linux上):
nasm -f elf64 m.asm -l m.lst -w+all; ld -b elf64-x86-64 -o m m.o
edb --run ./m
来源:
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
加法是在大多数CPU上左移1的最有效方法。与add same,same
(https://agner.org/optimize)相比,shl rdi,1
可以在更多的执行端口上运行,从而允许更多的指令级并行性,从而可能提高循环的吞吐量。