Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 有人知道如何使用汇编x86语言将N个奇数相加吗?_Assembly_X86 - Fatal编程技术网

Assembly 有人知道如何使用汇编x86语言将N个奇数相加吗?

Assembly 有人知道如何使用汇编x86语言将N个奇数相加吗?,assembly,x86,Assembly,X86,有人知道如何使用汇编x86语言和MUL助记符来计算N个奇数吗 例如:SUM=1*3*5*7*………*n要使用MUL指令相乘,您将一个数字放入eax(或rax或ax,具体取决于操作数大小)和另一个数字(在任何其他寄存器或内存中),然后执行MUL,并在edx:eax(或rdx:rax或dx:ax) 例如(32位,NASM语法,未测试): 当然,当它们是常量时,您可以欺骗它们,并让汇编程序在汇编代码时这样做。例如(32位,NASM语法,未测试): 您还可以在循环中执行MUL。例如,如果值来自表或数组(

有人知道如何使用汇编x86语言和MUL助记符来计算N个奇数吗
例如:SUM=1*3*5*7*………*n

要使用
MUL
指令相乘,您将一个数字放入
eax
(或
rax
ax
,具体取决于操作数大小)和另一个数字(在任何其他寄存器或内存中),然后执行
MUL
,并在
edx:eax
(或
rdx:rax
dx:ax

例如(32位,NASM语法,未测试):

当然,当它们是常量时,您可以欺骗它们,并让汇编程序在汇编代码时这样做。例如(32位,NASM语法,未测试):

您还可以在循环中执行
MUL
。例如,如果值来自表或数组(32位,NASM语法,未测试):

但是,如果这些值之间存在某种关系,则不需要表格。我认为您的顺序似乎错误,我怀疑您实际上想要“
1*3*5*7…N
”(并且怀疑
2
是一个打字错误),“
1*3*5*7…N
”是一个可以在没有表格的情况下完成的顺序。例如(32位,NASM语法,未测试):

请注意,您可以通过欺骗来提高性能。例如,您可以这样做(32位,NASM语法,未经测试):

使用预先计算的查找表可以欺骗更多的人。例如(32位,NASM语法,未测试):

当然,您可以像这样将表的大小减半:

    mov ecx,31                      ;ecx = N = 31
    shr ecx,1                       ;ecx = N/2 = 15
    mov eax,[resultTable + ecx*4]   ;eax = result for N
您还可以在运行时构建表,有效地将其转化为一种缓存:

    mov ecx,31                         ;ecx = N = 31

    mov edx,ecx                        ;edx = N
    shr edx,1                          ;edx = N/2
    cmp dword [resultTable + edx*4],0  ;Is the result for this N already known?
    je .unknown                        ; no, have to calculate it
    mov eax,[resultTable + edx*4]      ; yes, just use the result from last time
    jmp .done

.unknown:
    mov eax,1                          ;eax = the current result
    mov ebx,1                          ;ebx = the value the result was multiplied with last
    cmp ecx,9                          ;Is the last value greater than 9?
    jle .next                          ; no, don't cheat
    mov eax,1*3*5*7*9                  ; yes, cheat by skipping the first 4 multiplications
    mov ebx,9           

.next:
    lea ebx,[ebx+2]                    ;ebx = the value to multiply with the result next
    mul ebx                            ;edx:eax = new current result
    cmp ebx,ecx                        ;Has N been reached?
    jb .next                           ; no, keep going

    shr ecx,1                          ;ecx = N/2
    mov [resultTable + edx*4],eax      ;Store the result for next time

.done:
但是,以前任何较低值
N
的结果都可以作为计算较高值
N
的结果的起点。这导致了以下方法(32位,NASM语法,未测试):


欢迎使用堆栈溢出。请阅读,特别是和。最后学习如何创建。查找任何阶乘循环,并将其更改为递增2而不是1。为什么要使用一个操作数
mul ecx
,而不是像
imul eax,ecx
这样至少稍微更有效的操作数()?您希望扩展精度的结果比寄存器更宽吗?顺便说一句,
mul
不是“关键字”,这是一个指令助记符。是的,我的问题中有一个输入错误,但它已经被编辑。英语不是我的第一语言,我以前从未使用过stackoverflow,这是我第一次。我不使用IMUL的原因是因为我只知道一些助记符,如mov、add、sub和mul。奇怪的是,你没有提到一个操作数
mul
(Haswell上的3个uop)的效率低于imul eax、ebx(基本上所有设备上的1个uop)…使用
mul
是一种完全人为的约束,它会使代码变慢,并且只有在您真正想要高一半的结果时才有用。此外,使用两个累加器可以让您并行运行两个依赖关系链,分别执行
1*5*9*13*.
3*7*11*15*.
,并在最后将两者相乘。因为
>imul
至少有3个周期延迟,这将使大
n
的吞吐量翻倍(由于我们避免偶数,大
n
不仅会导致低32位都为零。因此模块化结果可能很有趣。)你的记忆/缓存方法很有趣,但你坚持在
ebx
中保留索引,这会使代码复杂化。如果你改为在ebx中保留
idx*2+1
(即你想乘以的东西),那么你就可以使用
addebx,2
/
imul eax,ebx
/
mov[resultable+ebx*2-2],eax
。您可以使用EDX而不是EBX。这里也没有理由使用
lea
而不是
add
;在Intel CPU上,您只是在整数乘法单元所在的端口1上产生了更多资源冲突的可能性。也许如果您正在为顺序原子进行调优?@PeterCordes:实际上;对于32位,这是可能的对于
N>=13
,y将溢出,如果它只适用于较小的
N
,则预计算的表(例如,可能不超过7个条目?)将比有代码的表更小、更容易。同样适用于64位(仅适用于
N@PeterCordes:Heh-示例代码是示例代码)(除了说明一个概念之外,没有其他理由存在,没有真正的理由对其进行优化,也没有真正的理由关心它是否正确或充满bug)。
    mov eax,[table]
    mov esi,table+4
    mov ecx,31-1            ;31 items in table?
.next:
    mul dword [esi]         ;edx:eax = temp * table[i]
    add esi,4
    loop .next
    mov ecx,31          ;ecx = N = 31
    mov ebx,1           ;ebx = the value the result was multiplied with last
    mov eax,1           ;eax = the result
.next:
    lea ebx,[ebx+2]     ;ebx = the value to multiply with the result next
    mul ebx             ;edx:eax = new current result
    cmp ebx,ecx         ;Has N been reached?
    jb .next            ; no, keep going
    mov ecx,31          ;ecx = N = 31

    mov eax,1           ;eax = the current result
    mov ebx,1           ;ebx = the value the result was multiplied with last
    cmp ecx,9           ;Is the last value greater than 9?
    jle .next           ; no, don't cheat
    mov eax,1*3*5*7*9   ; yes, cheat by skipping the first 4 multiplications
    mov ebx,9           

.next:
    lea ebx,[ebx+2]     ;ebx = the value to multiply with the result next
    mul ebx             ;edx:eax = new current result
    cmp ebx,ecx         ;Has N been reached?
    jb .next            ; no, keep going
    mov ecx,31                      ;ecx = N = 31
    mov eax,[resultTable + ecx*4]   ;eax = result for N
    mov ecx,31                      ;ecx = N = 31
    shr ecx,1                       ;ecx = N/2 = 15
    mov eax,[resultTable + ecx*4]   ;eax = result for N
    mov ecx,31                         ;ecx = N = 31

    mov edx,ecx                        ;edx = N
    shr edx,1                          ;edx = N/2
    cmp dword [resultTable + edx*4],0  ;Is the result for this N already known?
    je .unknown                        ; no, have to calculate it
    mov eax,[resultTable + edx*4]      ; yes, just use the result from last time
    jmp .done

.unknown:
    mov eax,1                          ;eax = the current result
    mov ebx,1                          ;ebx = the value the result was multiplied with last
    cmp ecx,9                          ;Is the last value greater than 9?
    jle .next                          ; no, don't cheat
    mov eax,1*3*5*7*9                  ; yes, cheat by skipping the first 4 multiplications
    mov ebx,9           

.next:
    lea ebx,[ebx+2]                    ;ebx = the value to multiply with the result next
    mul ebx                            ;edx:eax = new current result
    cmp ebx,ecx                        ;Has N been reached?
    jb .next                           ; no, keep going

    shr ecx,1                          ;ecx = N/2
    mov [resultTable + edx*4],eax      ;Store the result for next time

.done:
    mov ecx,31                    ;ecx = N = 31

    shr ecx,1                     ;ecx = N/2
    mov ebx,[highestN2]           ;ebx = the highest N/2 that's been done before
    cmp ecx,ebx                   ;Has this N/2 been done before?
    ja .unknown                   ; no
    mov eax,[resultTable + ecx*4] ; yes, use the previously calculated result
    jmp .done

.unknown:
    mov eax,[resultTable + ebx*4] ;eax = highest result previously calculated
.next:
    inc ebx                       ;ebx = next N/2 to use
    lea edx,[ebx*2+1]             ;edx = next N to use
    mul edx                       ;edx:eax = old result * N
    mov [resultTable + ebx*4],eax ;Store it for later
    cmp ebx,ecx                   ;Have we done enough?
    jb .next                      ; no, keep going
    mov [highestN2],ebx           ;Set the new highest N/2 calculated so far

.done: