Assembly 如何理解下面的代码片段
背景:由于在线课程,一些印度大学的计算机课程已经缩减为教师只给我们代码,并期望我们死记硬背 该程序用于计算给定数组中+ve和-ve个数 我的问题是从第45行到第59行(如下所示) 在上面的代码中,据我所知,我将数组的起始位置存储在ESI寄存器中,并扫描每个元素,检查它是否为正 但是,我如何知道何时到达数组的末尾 代码维护ECX寄存器,但不使用它。为什么这不是无休止地运行呢 是否也应该有某种带有DEC ECX和JE 0指令的循环 是否也应该有某种带有DEC ECX和JE 0指令的循环Assembly 如何理解下面的代码片段,assembly,x86,nasm,microprocessors,Assembly,X86,Nasm,Microprocessors,背景:由于在线课程,一些印度大学的计算机课程已经缩减为教师只给我们代码,并期望我们死记硬背 该程序用于计算给定数组中+ve和-ve个数 我的问题是从第45行到第59行(如下所示) 在上面的代码中,据我所知,我将数组的起始位置存储在ESI寄存器中,并扫描每个元素,检查它是否为正 但是,我如何知道何时到达数组的末尾 代码维护ECX寄存器,但不使用它。为什么这不是无休止地运行呢 是否也应该有某种带有DEC ECX和JE 0指令的循环 是否也应该有某种带有DEC ECX和JE 0指令的循环 这几乎就是所
这几乎就是所做的。循环下一个_num指令大致相当于
dec ecx;jnz next_num
。一个好的开始是在调试器中单步执行它以监视寄存器值的更改。如果loop
改变了ECX这一事实让您感到惊讶,请查阅指令集参考手册。此外,这是一种测试符号位的低效方法<代码>测试eax,eax/如果eax<0
(有符号比较),则jl阴性将是惯用的跳转方式。jl
条件基于符号标志,无需将其旋转为进位。您甚至可以cmp dword[esi],0
来比较内存操作数。还要注意,非负数包括零,这也不是正数。此外,无需更新循环内的两个计数器,只需使用shr eax,31
/添加ebx,eax
计算负数,并在最后计算非负=总负
。不需要分支,逐字累加符号位。@Peter Cordes:test eax,eax之后,你也可以使用js negative
,我发现这比使用jl
@ecm:yup更清楚,符号位本身有分支的语义,而值小于零则有分支。(jl
的语义更适合cmp eax,0
;针对寄存器本身进行测试是cmp
使用0的窥视孔优化,因此test/jl需要仔细考虑该语义,使其看起来自然。有趣的事实是:cmp reg,0
//code>js,它可以将cmp与js
。即使核心2也可以融合测试/js
,所以这两种习惯用法都可以)谢谢!我可能应该更多地阅读《英特尔开发人员手册》
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