LOOP(英特尔参考手动输入)递减ecx/rcx,然后如果非零则跳转.这很慢,但是英特尔不能廉价地把它变得很快吗? dec/jnz已经将宏观融合成 Sandybridge家族的一个 uop; 唯一的区别是设置标志.
loop关于各种微体系结构,来自Agner Fog的说明表:
Bulldozer-family/Ryzen:1 m-op(与宏观融合测试和分支相同,或者jecxz)
P4:4次(相同jecxz)
loope/ loopne).吞吐量= 4c(loop)或7c(loope/ne).loope/ loopne). 吞吐量=每5个循环一个,这是将循环计数器保留在内存中的瓶颈!jecxz只有2 uops,吞吐量与普通吞吐量相同jcc难道解码器不能像lea rcx, [rcx-1]/ 那样解码jrcxz吗?这将是3 uops.至少那是没有地址大小前缀的情况,否则它必须使用ecx和截断RIP,EIP如果跳转; 也许奇怪的地址大小选择控制减量的宽度解释了许多uops?
或者更好,只需将其解码为不设置标志的融合分支和分支? dec ecx …
我在Delphi中编写一个简单的BigInteger类型.它主要由TLimb的动态数组组成,其中TLimb是32位无符号整数,32位大小字段,它还保存BigInteger的符号位.
要添加两个BigIntegers,我创建一个适当大小的新BigInteger然后,在一些簿记之后,调用以下过程,将三个指针传递给左右操作数和结果的数组的相应开始,以及左右肢的数量分别为.
普通代码:
class procedure BigInteger.PlainAdd(Left, Right, Result: PLimb; LSize, RSize: Integer);
asm
// EAX = Left, EDX = Right, ECX = Result
PUSH ESI
PUSH EDI
PUSH EBX
MOV ESI,EAX // Left
MOV EDI,EDX // Right
MOV EBX,ECX // Result
MOV ECX,RSize // Number of limbs at Left
MOV EDX,LSize // Number of limbs at Right
CMP EDX,ECX
JAE @SkipSwap
XCHG ECX,EDX // Left and LSize should be largest
XCHG ESI,EDI // so swap
@SkipSwap:
SUB EDX,ECX // …Run Code Online (Sandbox Code Playgroud) 经过长时间的无数错误之后,希望这是最后的错误.
没有编译或运行时错误,只是一个逻辑错误.
编辑:(固定伪码)
我的伪代码:
first = 1;
second = 1;
third = 0;
for i from 1 to n{
third=first+second
first=second
second=third
}
return third
Run Code Online (Sandbox Code Playgroud)
这将打印该系列的最终结果.
我的汇编代码:
我尽可能地添加了评论
.386
.model flat,stdcall
option casemap:none
.data
timestell db "Loop Ran : %d Times -----",0 ;format string
fmtd db "%d",0
finalprint db "Final Number is : %d ------",0 ;format string
times dd 0Ah ;times to loop
first dd 1h
second dd 1h
third dd 0h
.data?
retvalue1 dd ? ;we will initialize it …Run Code Online (Sandbox Code Playgroud) (如果是这样的话,我会自己做的.)
我的问题:
为方便起见,我倾向于避免间接/索引寻址模式.
作为替代,我经常使用立即,绝对或寄存器寻址.
代码:
; %esi has the array address. Say we iterate a doubleword (4bytes) array.
; %ecx is the array elements count
(0x98767) myloop:
... ;do whatever with %esi
add $4, %esi
dec %ecx
jnz 0x98767;
Run Code Online (Sandbox Code Playgroud)
在这里,我们有一个序列化的组合(dec和jnz),它可以防止正常的乱序执行(依赖).
有没有办法避免/破坏dep?(我不是装配专家).
我想知道,有没有办法在xmm寄存器中增加一个值,或者你只能将一个值移动到一个?
我的意思是,你可以这样做:
inc eax
Run Code Online (Sandbox Code Playgroud)
或者像这样:
inc [ebp+7F00F000]
Run Code Online (Sandbox Code Playgroud)
有没有办法用xmm做同样的事情?
我尝试过类似的东西,但......它不起作用
inc [rbx+08]
movss xmm1,[rbx+08]
Run Code Online (Sandbox Code Playgroud)
我甚至尝试过一些非常愚蠢的东西,但它也没有用
push edx
pextrw edx,xmm2,0
add edx,1
mov [rbx+08],edx
movss xmm1,[rbx+08]
pop edx
Run Code Online (Sandbox Code Playgroud) 从头开始编程的挑战之一是“修改程序以使用结束地址而不是数字 0 来知道何时停止。”
\n我发现很难做到这一点,因为到目前为止,这本书只介绍了movl,,cmpl(incl以及寻址模式)和jmp指令。基本上,下面的代码片段中的所有内容都是到目前为止所介绍的。我发现的所有解决方案都涉及本书中尚未介绍的说明。下面的代码查找集合中的最大值。
.section .data\ndata_items: #These are the data items\n.long 3,67,34,222,45,75,54,34,44,33,22,11,66,0\n\n.section .text\n.globl _start\n_start:\n movl $0, %edi # move 0 into the index register\n movl data_items(,%edi,4), %eax # load the first byte of data\n movl %eax, %ebx # since this is the first item, %eax is\n # the biggest\nstart_loop: # start loop\n cmpl $0, %eax # check to see if we\xe2\x80\x99ve hit the end\n je loop_exit\n incl %edi # …Run Code Online (Sandbox Code Playgroud) 我的任务是编写一个程序来计算斐波那契数列的前七个值.给出的公式是:
Fib(1) = 1, Fib(2) = 1, Fib(n) = Fib(n-1) + Fib(n-2)
Run Code Online (Sandbox Code Playgroud)
我相信这是一个功能,但我不明白如何将其合并到代码中.我需要将值放在EAX寄存器中.我使用MASM并没有任何区别.任何提示?