为什么堆栈中始终存在无用的函数参数?

Lio*_*ion 6 assembly freebsd

我正在学习FreeBSD上的汇编语言编程.我正在使用FreeBSD 9.0 i386发行版和nasm汇编程序.

当我编写一个简单的系统调用函数时,我发现我必须将无用的值推入堆栈以使代码正确运行.

例如:

; File:test.asm
section .text
  global _start
_start:
  xor  eax,eax
  ; Argument of exit()
  push 0x0
  ; Syscall of exit()
  mov  al,1
  int  0x80
Run Code Online (Sandbox Code Playgroud)

我使用以下命令来汇编和链接上面的代码:

%nasm -f elf test.asm -o test.o
%ld test.o -o test.bin
Run Code Online (Sandbox Code Playgroud)

我用ktrace来检查程序,发现:

%ktrace ./test.bin
%kdump -d -f ./ktrace.out 
2059 ktrace   RET   ktrace 0
2059 ktrace   CALL  execve(-1077940941,-1077941260,-1077941252)
2059 ktrace   NAMI  "./test.bin"
2059 test.bin RET   execve 0
2059 test.bin CALL  exit(1)
Run Code Online (Sandbox Code Playgroud)

所以代码没有正确运行,因为我提供了0作为exit()的唯一参数,但程序实际上运行了exit(1).

然后我改变了我的代码.

; File:test.asm
section .text
  global _start
_start:
  xor  eax,eax
  push 0x0
  ; Whatever digits,0x1,0x2...0xFFFFFFFF, ect.
  push 0xFFFFFFFF
  mov  al,1
  int  0x80
Run Code Online (Sandbox Code Playgroud)

然后代码正确执行.

起初,我虽然是因为"堆栈填充"或"堆栈对齐"之类的东西,比如堆栈分配,填充和对齐.所以它可能会尊重16位对齐.但我发现它不是.例如,以下代码:

; File:test.asm
section .text
  global _start
_start:
  xor  eax,eax
  push 0x0
  ; Actual argument of exit()
  push 0x3
  push 0xFFFFFFFF
  ; Syscall of exit()
  mov  al,1
  int  0x80
Run Code Online (Sandbox Code Playgroud)

实际执行退出(3).它似乎没有对齐字节.我用gdb调试上面的代码,当最后一行即将执行时,堆栈是这样的:

0xFFFFFFFF  -> esp
0x00000003
0x00000000
Run Code Online (Sandbox Code Playgroud)

所以这是我的问题:为什么总会有一个无用的论点,或者有一种方法可以解决?

Jos*_*fer 7

通过阻止调用/返回指令对来稍微提高性能是一个伪参数.

请参阅以下链接中的2.1美元:

http://www.int80h.org/bsdasm/#default-calling-convention