相关疑难解决方法(0)

为什么循环指令慢?英特尔无法有效实施吗?

LOOP(英特尔参考手动输入)递减ecx/rcx,然后如果非零则跳转.这很慢,但是英特尔不能廉价地把它变得很快吗? dec/jnz已经将宏观融合成 Sandybridge家族的一个 uop; 唯一的区别是设置标志.

loop关于各种微体系结构,来自Agner Fog的说明表:

  • K8/K10:7 m-ops
  • Bulldozer-family/Ryzen:1 m-op(与宏观融合测试和分支相同,或者jecxz)

  • P4:4次(相同jecxz)

  • P6(PII/PIII):8次
  • Pentium M,Core2:11 uops
  • Nehalem:6个uops.(11为loope/ loopne).吞吐量= 4c(loop)或7c(loope/ne).
  • SnB家族:7个uops.(11为loope/ loopne). 吞吐量=每5个循环一个,这是将循环计数器保留在内存中的瓶颈!jecxz只有2 uops,吞吐量与普通吞吐量相同jcc
  • Silvermont:7次
  • AMD Jaguar(低功耗):8 uops,5c吞吐量
  • 通过Nano3000:2 uops

难道解码器不能像lea rcx, [rcx-1]/ 那样解码jrcxz吗?这将是3 uops.至少那是没有地址大小前缀的情况,否则它必须使用ecx和截断RIP,EIP如果跳转; 也许奇怪的地址大小选择控制减量的宽度解释了许多uops?

或者更好,只需将其解码为不设置标志的融合分支和分支? dec ecx …

performance x86 assembly intel cpu-architecture

53
推荐指数
3
解决办法
6096
查看次数

为什么循环总是被编译成"do ... while"样式(尾部跳转)?

当试图理解汇编(启用编译器优化)时,我看到这种行为:

这样一个非常基本的循环

outside_loop;
while (condition) {
     statements;
}
Run Code Online (Sandbox Code Playgroud)

经常被编译成(伪代码)

    ; outside_loop
    jmp loop_condition    ; unconditional
loop_start:
    loop_statements
loop_condition:
    condition_check
    jmp_if_true loop_start
    ; outside_loop
Run Code Online (Sandbox Code Playgroud)

但是,如果未打开优化,则会编译为通常可理解的代码:

loop_condition:
    condition_check
    jmp_if_false loop_end
    loop_statements
    jmp loop_condition  ; unconditional
loop_end:
Run Code Online (Sandbox Code Playgroud)

根据我的理解,编译后的代码更像是这样的:

goto condition;
do {
    statements;
    condition:
}
while (condition_check);
Run Code Online (Sandbox Code Playgroud)

我看不到巨大的性能提升或代码可读性提升,为什么经常出现这种情况呢?是否有此循环样式的名称,例如"尾随条件检查"?

optimization performance assembly loops micro-optimization

26
推荐指数
1
解决办法
1675
查看次数

汇编 8086,LOOP 指令没有停止

以下代码适用于程序集 8086,我正在使用LOOP指令进行循环。

CL变为零后,循环将永远继续,并将CX值更改为 FFFFh。
但是,如果我将 的值更改CL为最大 06h,则循环会正确停止。
此外,如果我先删除LOOP AGAIN它会正常工作。

DATA DB 01001100b

MOV AL, DATA
MOV CL, 08h
SUB BL, BL
SUB DL, DL

AGAIN:
ROL AL, 1  
JC SKIP
INC BL
LOOP AGAIN

SKIP: 
INC DL
LOOP AGAIN
Run Code Online (Sandbox Code Playgroud)

我希望它在CL变为零时停止。知道为什么它没有按预期运行吗?

更新 1 我注意到当CL(或CX当使用 16 位时)达到 1 并且最后一位为 0,那么第一个LOOP AGAIN不会跳起来并且操作继续到SKIP部分。如果我将DATA的最后一位更改为 1,它将使JC SKIP一切正常。

assembly loops x86-16

3
推荐指数
1
解决办法
2478
查看次数

是否有不同 x86_64 操作和 C std lib 函数使用的寄存器列表?

我开始在 ubuntu linux 上使用 NASM 汇编器学习 x86_64 汇编编程。我遇到的问题之一是弄清楚操作神奇地使用了哪些寄存器。

我正在阅读的书有这样的代码示例:

mov    rdi, fmt1
mov    rsi, strng
mov    rax, 0
call   printf

; How am I supposed to know which registers are used by the call to printf? 
; The libc printf function supports an arbitrary number of parameters. 
; Clearly there aren't an unlimited number of registers in x86_64 so how does this work
; as the parameter list grows?
Run Code Online (Sandbox Code Playgroud)

代码示例的另一部分是这样的:

xor    rax, rax
mov    rbx, strng
mov    rcx, strLen
mov …
Run Code Online (Sandbox Code Playgroud)

assembly x86-64 nasm calling-convention

3
推荐指数
1
解决办法
452
查看次数

在Turbo Debugger中单步执行时,LOOP只执行一次

代码必须输出'ccb',但只输出'c',只输出LOOP一次,我已在TD中校准,但为什么LOOP只做一次?

我认为我必须减少STRING_LENGTH,所以我心烦意乱

DEC STRING_LENGTH
Run Code Online (Sandbox Code Playgroud)

但是它不起作用,所以我很喜欢这样

MOV SP,STRING_LENGTH
DEC SP
MOV STRING_LENGTH,SP
Run Code Online (Sandbox Code Playgroud)

我知道你现在正在思考什么,这是不正确的,你是对的)))

我可以使用C++,但我只想在大会上做,

DOSSEG
.MODEL SMALL
.STACK 200H
.DATA
STRING DB 'cScbd$'
STRING_LENGTH EQU $-STRING
STRING1 DB STRING_LENGTH DUP (?) , '$'
.CODE
MOV AX,@DATA
MOV DS,AX
XOR SI,SI
XOR DI,DI

MOV CX,STRING_LENGTH

S:

MOV BL,STRING[DI]
AND STRING[DI],01111100B
CMP STRING[DI],01100000B
JNE L1
MOV AL,BL
MOV STRING1[SI],AL
ADD SI,2
L1:

ADD DI,2

LOOP S

MOV DL,STRING1
MOV AH,9
INT 21H
MOV AH,4CH
INT 21H
END
Run Code Online (Sandbox Code Playgroud)

debugging assembly x86-16

1
推荐指数
1
解决办法
85
查看次数