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

时间:2017-03-19 16:57:09

标签: loops assembly x86

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

        section .text                                                                                    
        global _start                                                                                    
_start:                                                                                                                                                                                               
        mov ebx, 1                                                                                       
        mov ecx, string                                                                                  
        mov edx, string_len                                                                              
        mov eax, 4                                                                                      
        int 0x80                                                                                                                                                                          
        mov eax, 1                                                                                       
        int 0x80                                                                                         

        section .data                                                                                    
        string db "Hello World!", 10, 0                                                                  
        string_len equ $ - string

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

 mov ecx, 5
 start_loop:
 ; the code here would be executed 5 times
 loop start_loop

问题:我试图在我的代码上实现循环,但它输出一个无限循环。我还注意到循环需要ECX,写函数也需要ECX。显示10次“Hello World!”的正确方法是什么? ?

这是我当前的代码(产生无限循环):

        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

非常感谢

1 个答案:

答案 0 :(得分:5)

loop使用ecx寄存器。这很容易记住,因为c代表counter。但是,您会覆盖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                         

没有正确或错误的循环方式 除非您正在寻找最后一个周期,否则您不会,因为您已经在循环中进行了系统调用。

loop的缺点是它比同等sub ecx,1 - jnz start_of_loop略慢。

loop的优点是它使用较少的指令字节。

请注意,对于稍微较旧的CPU(过去3年),不建议使用dec reg + jcc label。由于dec仅改变标志寄存器的一部分,因此可能导致部分寄存器写入停顿,导致后续读取jnz的标志寄存器停止一个周期。
这已在最新的英特尔和AMD处理器中得到修复。 sub reg,1 + jnz在未来5年仍然是一个好主意。

使用int 80h进行的系统调用不会改变除eax以外的任何寄存器,因此只要您记得不要弄乱edi,您就不需要推送/ {流行对。