Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/git/24.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 x86汇编:循环!_Loops_Assembly_X86_Nasm - Fatal编程技术网

Loops x86汇编:循环!

Loops x86汇编:循环!,loops,assembly,x86,nasm,Loops,Assembly,X86,Nasm,好的,长话短说,我正在学习汇编,我正在尝试做一个循环,打印出ascii字符“0”-“9”。 所以,我做了我在示例中看到的所有基础工作,比如用pushad和popad保存寄存器状态,分配堆栈空间,确保事情按照开始的方式进行。 所以我管理了这个小例子: ; ; Hello_World.asm ; (NASM Syntax, Windows) extern _printf section .text _main: pushad ; save re

好的,长话短说,我正在学习汇编,我正在尝试做一个循环,打印出ascii字符“0”-“9”。 所以,我做了我在示例中看到的所有基础工作,比如用pushad和popad保存寄存器状态,分配堆栈空间,确保事情按照开始的方式进行。 所以我管理了这个小例子:

;
; Hello_World.asm
; (NASM Syntax, Windows)

    extern _printf

    section .text

_main:
  pushad                ; save register states

  push  ebp             ; save old stack
  mov       ebp, esp    ; prepare new stack
  sub       esp, 1*4    ; allocate 4 bytes

  mov       byte [esp + 0], 48  ; add ascii '0' to stack
  mov       byte [esp + 1], 0   ; add ascii NULL terminator to stack

  push  esp;        ; push the string in the stacks refrence 
  call  _printf     ; call printf()
  add   esp, 4      ; pop string refrence

  add   esp, 1*4    ; deallocate 4 bytes
  mov   esp, ebp    ; close this stack
  pop   ebp         ; restore old stack

  popad             ; restore register states
  ret               ; leave this function
这是可行的,它打印出“0”,但这有点安全。我试着给它加上一个循环,但是事情就这样破裂了。我读到“循环”操作码应该减少ECX寄存器,如果ECX>0,则返回标签参数,但是,我认为我还没有完全理解它

因此,我添加了几行,并得出以下结论:

;
; Hello_World.asm
;

    extern _printf
    global _main

    section .text

_main:
  pushad                ; save register states

  push  ebp         ; save old stack
  mov   ebp, esp    ; prepare new stack
  sub   esp, 1*4    ; allocate 4 bytes

  mov   byte [esp + 0], 48  ; add ascii '0' to stack
  mov   byte [esp + 1], 0   ; add ascii NULL terminator to stack

  mov   ecx, 9      ; set loop counter to 9

aLoop:
  inc   byte [esp + 0]  ; increment ascii character 
  push  esp;        ; push the string in the stacks refrence 
  call  _printf     ; call printf()
  add   esp, 4      ; pop string refrence
  loop  aLoop           ; loop back to aLoop if ecx > 0

  add   esp, 1*4    ; deallocate 4 bytes
  mov   esp, ebp    ; close this stack
  pop   ebp         ; restore old stack

  popad             ; restore register states
  ret                   ; leave this function
好吧,现在事情变得疯狂了。我在命令提示符下运行它,我通过耳机听到嘟嘟声,它在每一个ascii字符中循环,将它们全部打印出来。所以在飞行角色5秒钟后,我假设有东西溢出,然后它就崩溃了

我对汇编相当陌生(今天是我真正编程的第一天),我不知道出了什么问题。有人能解释一下我如何更好地实现循环吗

谢谢你!
-Jason

好吧,你要描述的是,循环没有因为某种原因而终止。这意味着问题必须在这里:

  add   esp, 4      ; pop string refrence
  loop  aLoop       ; loop back to aLoop if ecx > 0
这听起来像是调试器的工作:ecx到底发生了什么

我注意到您正在将
ecx
设置为
9
。然后将
4
添加到
esp
。您什么时候更改ecx?(是的,我知道它应该发生在
循环
指令中,但如果它起作用,你就不会问了。
ecx
到底发生了什么?)

顺便说一句,哔哔声很容易:当你在所有ASCII字符中循环时,你碰到的是ASCII 0x07,即BEL字符。

子例程是否保留ECX的内容?如果不是,那可能是你的问题。试着在通话中保存它

aLoop:
  inc   byte [esp + 0]  ; increment ascii character
  push  ecx;        ; save ecx
  push  esp;        ; push the string in the stacks refrence
  call  printf     ; call printf()
  add   esp, 4      ; pop string refrence
  pop   ecx
  loop  aLoop           ; loop back to aLoop if ecx > 0

调用方保存的寄存器为eax、ecx、edx。允许被调用的子例程修改这些寄存器。使用搜索引擎查找调用者保存的寄存器与被调用者保存的寄存器。应该会给您提供更多详细信息。

是的,接下来我可能会找到一个好的调试器(有什么建议吗?)。但我的理解是“循环”指令应该减少ECX寄存器,然后进行比较,但这似乎没有发生。也许我最好切换到正常的比较和跳转…您已经在那里调用了_printf(顺便说一句,您确定调用顺序正确吗?),因此您可以尝试打印ecx的值。至于调试器,我不了解您的环境。你有nasm,所以我想可能是Windows;你有VisualStudio吗?经过快速检查,这就解决了它!现在,只要将ecx快速推/弹出到堆栈,并进行一些操作来维护我的字符串引用,它就可以完美地工作!非常感谢,这是一个我以后必须注意的问题。@Jason请将此答案标记为您的问题的解决方案。
loop
很慢。此外,在这种情况下,您应该避免使用push/pop。只需使用被调用方保存的ebx作为计数器。循环条件为:
DEC EBX;JNZ aLoop
Ahh,但是您可以看到,通过在字符串引用之前按ecx,esp现在指向其他东西!虽然只需稍加操纵,但一切都能正常工作。谢谢你!我上一次使用x86汇编是在20年前,正是这样的事情提醒了我,我没有错过它。啊,谢谢你告诉我要保存哪些寄存器,这将在将来是一个很大的帮助。迈克·德西莫内,我觉得这样的小事很有趣,我这样做是为了迎接挑战,但是是的,这很乏味。哦,别误会,这很有趣。我上了一个学期的课,我们只做了8086(没有E_uuu_uuu寄存器),386刚出来,所以是的,近距离和远距离指针。但与此同时,为了好玩,我在Mac电脑上写了68000个汇编,我更喜欢寄存器文件,而不是过于专业化的寄存器,这需要大量数据移动才能实现更复杂的算法。