为什么在nasm中使用外部c函数会破坏此代码?

为什么在nasm中使用外部c函数会破坏此代码?,c,assembly,external,nasm,C,Assembly,External,Nasm,我在使用外部c函数调试nasm程序时遇到了一个问题 %macro pint 1 pushad push %1 call printint popad %endmacro section .text extern printint global main main: mov eax, 3 pint eax dec eax pint eax mov eax,1 mov ebx,0

我在使用外部c函数调试nasm程序时遇到了一个问题

%macro pint 1
  pushad
  push %1
  call printint
  popad
%endmacro

section .text
      extern printint
      global main
   main:
      mov eax, 3
      pint eax
      dec eax
      pint eax

      mov eax,1
      mov ebx,0
      int 0x80
printint的定义如下:

 void printint(int a) { 
   printf("%d\n",a);
 }
我得到的输出是第一次打印的3(如预期的)和第二次打印的随机数。 我被告知printf()可能会更改cpu寄存器值而不还原它们,因此我认为在调用printf之前保存堆栈上的所有寄存器可以防止任何寄存器更改,但显然不会更改。
有人能解释为什么会有奇怪的输出吗?我该如何修复它

谢谢。

printint()
可能正在使用调用约定。根据该约定,调用方负责从堆栈中删除推送的参数

你应该写:

%macro pint 1
    pushad
    push %1
    call printint
    add esp, 4  ; Clean pushed parameter.
    popad
%endmacro

您似乎正在为Linux编写代码(取决于您终止程序的方式)。在这个系统上,只有EAX、ECX和EDX中的值会被调用阻塞。此外,从
main
返回值比手动调用
\u exit
系统调用要好:
mov eax,0;ret
。对于
printint
函数来说,这可能不是问题,但一般来说,堆栈指针在
调用
完成隐式推送后必须始终可以被16整除(因此在
printint
中推送参数之前,应该
sub eax,8
,然后撤消该操作)。弗里德里克对你实际问题的诊断是正确的。