gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-02 04:57:24 25 4
gpt4 key购买 nike

我目前正在学习汇编语言,并且我有一个输出“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

非常感谢

最佳答案

loop使用 ecx登记。这很容易记住,因为 c代表counter 。但是,您会覆盖 ecx注册这样就永远行不通了!

最简单的解决方法是为循环计数器使用不同的寄存器,并避免 loop说明。

    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的缺点是it's slower比同等的sub ecx,1 ; jnz start_of_loop

loop的优势是它使用更少的指令字节。将其视为一种代码大小优化,如果 ECX 恰好是一个方便的循环寄存器,您可以使用它,但以某些 CPU 上的速度为代价。

<小时/>

请注意使用dec reg + jcc label is discouraged for some CPUs (Silvermont/Goldmont 仍然相关,Pentium 4 则不相关)。因为dec仅更改部分标志寄存器,可能需要额外的合并微指令。主流 Intel 和 AMD 分别重命名了 EFLAGS 的部分内容,因此 dec 不会受到任何惩罚。/jnz (因为 jnz 只读取 dec 写入的标志之一),甚至可以微融合到 Sandybridge 系列上的 dec-and-branch uop 中。 (但 sub 也可以)。 sub除了代码大小之外,永远不会更糟,因此您可能需要使用 sub reg,1在可预见的 future 。

使用int 80h的系统调用不更改除 eax 之外的任何寄存器,所以只要你记住不要乱搞edi你不需要push/pop对。选择一个在循环内不使用的寄存器,或者您可以直接使用堆栈位置作为循环计数器,而不是寄存器的压入/弹出。

关于loops - 如果我在循环中使用 ECX(汇编),正确的循环方法是什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42889387/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com