Loops 如果我在循环(汇编)中使用ECX,正确的循环方式是什么
我目前正在学习汇编语言,我有一个输出“Hello World!”的程序: 我理解这个代码是如何工作的。但是,现在,我想显示10倍的直线。我在互联网上看到的循环代码如下:Loops 如果我在循环(汇编)中使用ECX,正确的循环方式是什么,loops,assembly,x86,Loops,Assembly,X86,我目前正在学习汇编语言,我有一个输出“Hello World!”的程序: 我理解这个代码是如何工作的。但是,现在,我想显示10倍的直线。我在互联网上看到的循环代码如下: mov ecx, 5 start_loop: ; the code here would be executed 5 times loop start_loop 问题:我试图在代码上实现循环,但它输出一个无限循环。我还注意到循环需要ECX,写入函数也需要ECX。显示10次“Hello World!”的正确方式是什么 这
mov ecx, 5
start_loop:
; the code here would be executed 5 times
loop start_loop
问题:我试图在代码上实现循环,但它输出一个无限循环。我还注意到循环需要ECX
,写入函数也需要ECX
。显示10次“Hello World!”的正确方式是什么
这是我当前的代码(生成无限循环):
非常感谢
循环
使用ecx
寄存器。这很容易记住,因为c
代表计数器
。但是,您将覆盖ecx
寄存器,这样就永远不会工作
最简单的修复方法是为循环计数器使用不同的寄存器,并避免使用循环
指令
mov edi,10 ;registers are general purpose
loop:
..... do loop stuff as above
;push edi ;no need save the register
int 0x80
.... ;unless you yourself are changing edi
int 0x80
;pop edi ;restore the register. Remember to always match push/pop pairs.
sub edi,1 ;sub sometimes faster than dec and never slower
jnz loop
没有正确或错误的循环方式。(除非你在寻找每一个最后的循环,而你不是,因为你在循环中有一个系统调用。)
循环
的缺点是,与等效的子ecx相比,1
<代码>jnz启动\u循环的\u
循环
的优点是使用更少的指令字节。如果ECX恰好是一个方便的循环寄存器,那么可以将其视为一种代码大小优化,但要以某些CPU的速度为代价
请注意,
dec reg
+jcc标签的使用
(Silvermont/Goldmont仍然相关,奔腾4则不相关)。由于dec
仅更改部分标志寄存器,因此可能需要额外的合并uop。主流Intel和AMD分别重命名EFLAG的一部分,这样就不会对dec
/jnz
(因为jnz
只读取dec
编写的一个标志),甚至可以微融合到dec和Sandybridge系列的分支uop中。(但是sub
)也可以sub
除了代码大小外,从来都不会更差,因此您可能希望在可预见的将来使用sub reg,1
使用
int 80h
的系统调用不会改变除eax
以外的任何寄存器,因此只要记住不要弄乱edi
,就不需要push/pop对。选择一个不在循环中使用的寄存器,或者您可以直接使用堆栈位置作为循环计数器,而不是按下/弹出寄存器。您好,Johan,非常感谢您的完美回答。我只有一个问题:为什么循环使用edi?(而不是ecx)?多谢各位much@void为什么它要与ecx一起工作ecx
已被sys_写入使用,因此除非您想通过在每次sys_写入调用之前存储/恢复计数器值来解决冲突,否则您只需放弃ecx
并使用任何其他空闲寄存器即可。顺便说一句,不要使用loop
指令(除非为256字节的intro编码),使用dec ecx
jnz start\u loop
(类似于“loop”指令,可以与任何寄存器一起用作计数器)<代码>循环人为地变慢,并固定为ecx
。
section .text
global _start
_start:
mov ecx, 10
myloop:
mov ebx, 1 ;file descriptor
mov ecx, string
mov edx, string_len
mov eax, 4 ; write func
int 0x80
loop myloop
mov eax, 1 ;exit
int 0x80
section .data
string db "Hello World!", 10, 0
string_len equ $ - string
mov edi,10 ;registers are general purpose
loop:
..... do loop stuff as above
;push edi ;no need save the register
int 0x80
.... ;unless you yourself are changing edi
int 0x80
;pop edi ;restore the register. Remember to always match push/pop pairs.
sub edi,1 ;sub sometimes faster than dec and never slower
jnz loop