汇编语言- 保留寄存器值?

3

我在使用汇编语言中创建的函数中,遇到了一些问题,我认为这与printf有关。我创建的函数如下:

printnstars:
    movl $0, %edi
    movl 4(%esp), %ebx

starloop:
    cmpl %ebx, %edi
    je exitloop
    incl %edi
    pushl $star
    call printf
    addl $4, %esp
    jmp starloop

exitloop:
    ret

该函数以一个数字作为参数,我将其移至%ebx,并使用以下代码打印相应数量的“*”:

star:
    .asciz "*"

该函数执行了它应该完成的任务,但是当我尝试像这样做一些事情时遇到了问题:
    pushl (%ecx)
    call printnstars
    pushl (%ecx)
    call printnstars

当 (%ecx) 等于 2 时,如果我只进行一次调用,它的表现符合预期并打印出2个星号,但当我再次调用它时,它会打印无数个星号。很明显,在 printf 函数内部 %ecx 必须已经被篡改了,因为我没有在自己创建的任何内容中使用该寄存器。我该怎么做才能确保在多次调用 printnstars 时 (%ecx) 的值保持不变呢?
此外,也许需要注意的是,这是在一个函数内使用的,该函数打印带有星号的直方图,每行星号表示数字出现的次数。 我所有基于 %ecx 的频率值,所以我正在使用 (%ecx)。

1
杰克,请停止篡改你的问题。我不会删除它,因为这是一个好问题,有一个好答案。 - Brad Larson
1个回答

2
我该如何确保在多次调用printnstars时,(%ecx)的内容不会改变?
您可以将寄存器的值保存在堆栈上的局部变量中。
此外,请记住,printf()接受可变数量和类型的参数,因为它不知道有多少个参数和它们的类型,所以它不会移除堆栈上的参数。从堆栈中移除它们(通过调整esp)成为调用者的责任。

好的,那么我是在第一个调用之前添加pushl %ecx,然后在第二个调用之前添加popl %ecx吗?另外,在printf调用之后,我确实执行了addl $4, %esp,所以我做得正确吧...? - zProgrammer
你可以将其推两次,然后也调用函数两次。这样怎么样?并且要注意printf的栈参数。 - Alexey Frunze
不是addl $4 %esp就可以解决这个问题吗? - zProgrammer
啊,我错过了。它很可能是这样的。 - Alexey Frunze
好的,我进行了两次推送,然后调用了两次,看起来可以工作 :) 谢谢。 - zProgrammer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接