Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Loops 如果我在循环(汇编)中使用ECX,正确的循环方式是什么_Loops_Assembly_X86 - Fatal编程技术网

Loops 如果我在循环(汇编)中使用ECX,正确的循环方式是什么

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!”的正确方式是什么 这

我目前正在学习汇编语言,我有一个输出“Hello World!”的程序:

我理解这个代码是如何工作的。但是,现在,我想显示10倍的直线。我在互联网上看到的循环代码如下:

 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