Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/6.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
Assembly 为什么此代码会导致程序集中出现infinte循环_Assembly_X86 - Fatal编程技术网

Assembly 为什么此代码会导致程序集中出现infinte循环

Assembly 为什么此代码会导致程序集中出现infinte循环,assembly,x86,Assembly,X86,我在Assemby中有一小段代码,它基本上是通过循环运行的,并以相反的顺序打印值,但当我运行时,它会转到infinte循环。下面是代码 section .data x db "value=%d" section .text global main extern printf main: mov eax, 10 well_done: push eax push x call printf add esp,8 dec eax cmp eax ,0 jnz well_done ret 调用函数时,

我在Assemby中有一小段代码,它基本上是通过循环运行的,并以相反的顺序打印值,但当我运行时,它会转到infinte循环。下面是代码

section .data
x db "value=%d"
section .text
global main
extern printf
main:
mov eax, 10
well_done:
push eax
push x

call printf
add esp,8
dec eax
cmp eax ,0
jnz well_done
ret

调用函数时,必须确定使用了哪些寄存器。如果调用C函数,
eax
可以用于函数需要的任何功能,因此在执行函数之前必须
push eax
,在函数返回后,可以
pop
执行它

section .data
x db "value=%d"
section .text
global main
extern printf
main:
mov eax, 10
well_done:
push eax   <- save the counter
push eax   <- argument for printf
push x

call printf
add esp,8   <- clears the stack with the arguments for printf
pop eax   <- restore the counter
dec eax
cmp eax ,0
jnz well_done
ret
section.data
x db“值=%d”
第节.案文
全球主要
外部打印
主要内容:
mov-eax,10
干得好:

推eax谢谢大家的帮助。这就是我按照哈罗德的建议所做的。谢谢哈罗德

section .data
x db "value=%d"
section .text
global main
extern printf
main:
mov ebx, 10
well_done:
push ebx
push x

call printf
add esp,4
pop ebx
dec ebx
cmp ebx ,0
jnz well_done
ret

由于注释太长,我只想把它放在这里:我使用被叫保存寄存器的意思是这样的

section .data
x db "value=%d"

section .text
global main
extern printf

main:
  mov ebx, 10
well_done:
  push ebx
  push x
  call printf
  add esp, 8
  dec ebx
  jnz well_done
  ret

请注意,通常使用
ebx
意味着您应该在进入时保存
ebx
,并在退出时将其还原,但由于这是
main
,因此我们可以不这样做。

有推送但没有弹出?
eax
是调用方保存在cdecl中,
printf
可能正在扼杀它的生命value@kerrek我想知道为什么在这种特殊情况下需要pop。我不知道-我不是说我理解它,我只是注意到了不对称性。无论如何,你不能从中恢复它,一个函数可能会修改它的参数-这不太常见,但你不能真正依赖它。您可以两次按下eax(显然在调用后弹出),或者使用被调用方保存寄存器,如
ebx
,总之@Devolus使用寄存器eax对我来说也很好,用eax替换ebx没有什么区别。这实际上不是我想要的,我的意思是使用
ebx
,然后不恢复它,你不必还原它,printf本身必须还原ebx,是的,我知道。我不知道有这样的被调用方保存约定存在。就“返回值不会被推送,而是在eax中执行(在大多数情况下是这样)”,我相信在执行任何调用printf的地方,它要做的第一件事就是将返回推送到堆栈,而不是改变esp,这是Peter Wright在年告诉我的在这个问题的答案中。你想说些同样的话吗。哦,回信地址,是的,一个
呼叫
按下按钮,然后跳转。一个
ret
弹出地址*并跳转到它。*它弹出某个内容并将其解释为一个地址,而不管它是否实际是一个有效的地址。那么更改ESP呢?将调用push来更改ESP吗?最后一点,为什么在代码中添加esp,8是必需的,无论如何ebx的值为10,我们可以使用它,而无需将esp指向正确的位置。
call
ret
change
esp
yes
add esp,8
是清除您给出的参数
printf
(与stdcall不同,在cdecl中,调用者清除堆栈)。您可以暂时不清理堆栈,但是最后一个
ret
将弹出错误的东西,可能会崩溃。如果循环更长,堆栈溢出也可能成为一个问题。再次感谢Harold的友好输入,这将对我今后的工作有很大帮助。