2013-04-26 110 views
1

我目前正在学习英特尔x86汇编,并且在尝试构建循环10次的简单循环时遇到了问题。它应该在10个循环后停止,但它会一直持续下去。英特尔x86汇编中的循环永远持续

这是我使用的代码:

section .data 
    msg  db  "Hello, World!", 0x0a 
    len  equ  $-msg 

    section .text 
    global _start 

    _start: 
      mov  cx, 10 ; loop counter 

      _loop_start: 
        mov  ebx, 0x01 
        mov  ecx, msg 
        mov  edx, len 
        mov  eax, 0x04 
        int  0x80 

        dec  cx 
        cmp  cx, 0 
        jge  _loop_start 

      _done: 
        mov  ebx, 0x00 
        mov  eax, 0x01 
        int  0x80 

之前尝试写这样的代码,我看着this tutorial做简单的算术。

予编译它像这样:

nasm -f elf64 test.s -o test.o 

和链路这样的:预先

ld -s -o test_exec test.o 

谢谢, Anickyan

回答

4

CX是ECX的低16位部分。你的代码表明你可能认为你的循环将运行10次(在循环之前你将cx设置为10)。但是,你用覆盖地址为msg的值覆盖mov ecx, msg。所以你会从该数字的低16位开始倒数到0。 但是减量甚至没有效果,因为在下一次迭代期间,您会用msg的地址再次覆盖ecx。循环再次开始。这是一个无限循环。 您是否在调试器中检查软件?这可以帮助很多。

+0

啊。谢谢!我感觉有什么东西在覆盖它,但我不知道cx和ecx是一个(有点) – Anickyan 2013-04-26 07:22:25

+0

@Anickyan [This](http://upload.wikimedia.org/wikipedia/commons/4/41/Table_of_x86_Registers .png)图像会给你一个'寄存器层次结构'的概念。 – Aaron 2013-04-26 12:07:47

+3

@ JesusPlusPlus11漂亮的图像,但它缺少一些x86-64寄存器:'sil','dil','bpl','spl'。忽略这些子寄存器与包含其他x86-64通用寄存器不一致。它**完全错误**将'sp'和'esp'作为'rip'的子寄存器! – nrz 2013-04-26 14:33:40

0

如果“覆盖”问题得到解决,并且如果我们用10的计数器开始减少每个电路的计数器,并且如果我们在计数器的值大于或等于0时分支,则我们变成循环11次。

Alternativly我们还可以使用zeroflag分支(如果zeroflag未设置):

   dec  cl 
       jnz  _loop_start 

的“DEC”的指令已经涉及到标志寄存器,所以我们并不需要“CMP” - 指令,如果我们想检查一个值是否下降到零。

Dirk