【问题标题】:How to understand the snippet of code below [duplicate]如何理解下面的代码片段[重复]
【发布时间】:2020-09-13 07:32:39
【问题描述】:

对于上下文:由于在线课程,一些印度大学的计算机课程已经减少为老师,他们只是给我们代码并期望我们死记硬背。

程序是计算给定数组中 +ve 和 -ve 数字的数量。 The entire code is here.

我的问题是从第 45 行到第 59 行(如下所示)

mov    esi, arr
mov    ecx,arr_size         ;Array counter i.e. 6 
mov    ebx,0;                   ;counter for     +ve nos
mov    edx,0;                   ;counter for    -ve nos.

next_num:
    mov    eax,[esi]         ; take no. in RAX
    rcl    eax,1             ; rotate left 1 bit to check for sign bit
    jc    negative
positive:
    inc    ebx            ; no carry, so no. is +ve
    jmp    next
negative:
    inc    edx            ; carry, so no. is -ve
next:
    add  esi,4                ; 32 bit nos i.e. 4 bytes
    loop next_num

在上面的代码中,据我所知,我将数组的起始位置存储在 ESI 寄存器中并扫描每个元素并检查它是否为正

但是,我如何知道何时到达数组的末尾?

代码正在维护 ECX 寄存器,但不使用它。那为什么不是无限运行呢?

难道不应该有某种带有 DEC ECX 和 JE 0 指令的循环吗?

【问题讨论】:

  • loop next_num 指令大致等价于dec ecx; jnz next_num
  • 一个好的开始是在调试器中单步执行它以观察寄存器值的变化。然后,如果 loop 更改了 ECX 让您感到惊讶,请查看指令集参考手册。
  • 另外,这是一种测试符号位的低效方法。如果EAX < 0(有符号比较),test eax,eax / jl negative 将是跳转的惯用方式。 jl 条件基于符号标志,无需将其轮换为进位。你甚至可以cmp dword [esi], 0 来比较一个内存操作数。另请注意,非负数包括零,这也不是正数。此外,无需更新循环内的两个计数器,只需用shr eax, 31 / add ebx, eax 计算负数,最后计算non_neg = total - negative。不需要分支,直接将符号位相加。
  • @Peter Cordes:在test eax, eax 之后,您还可以使用js negative,我觉得这比使用jl 更清晰。
  • @ecm:是的,符号位本身存在分支的语义含义,而在小于零的值上存在分支。 (jl 的语义含义更适合cmp eax, 0;针对自身测试寄存器是cmp 0 的窥视孔优化,因此 test/jl 需要仔细考虑该含义以使其看起来自然。有趣的事实: cmp reg,0 / js 将是 slower on Core 2,可以将 cmp 与 jl 进行宏融合,但不能将 js 融合。即使 Core 2 也可以融合 test/js,所以任何一个成语都可以)

标签: assembly x86 nasm microprocessors


【解决方案1】:

难道不应该有某种带有 DEC ECX 和 JE 0 指令的循环吗?

loop instruction 几乎就是这样做的。

【讨论】:

  • 谢谢!我应该更多地阅读英特尔开发者手册
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多