2

我在让我在 Linux 上编写的最简单的汇编程序在我的 FreeBSD 机器上运行时遇到了问题。这是有问题的代码(我试图让它尽可能简单):

#counts to sixty
 .section .data
 .section .text
 .global _start
_start:
 movl $1, %ecx           #move $1 into ecx
 movl $1, %eax
start_loop:
 addl %ecx, %eax        #add ecx to eax
 cmpl $60, %eax         #compare $60 and eax...
  je end_loop            #if eax = 60 go to end_loop
 cmpl $60, %eax #
  jle start_loop         #jump if eax is < $60...
  jmp start_loop         #...to start_loop

 end_loop:
  movl %eax, %ebx        #move the value of eax into ebx because ebx holds
                         #the return value
  movb $1, %al           #Move $1 into eax (int 1 is the value for the 
                         #exit() syscall
  int $0x80

Linux 机器返回预期结果,即 60,而 FreeBSD 机器始终返回 164 作为返回码。有人知道这是为什么吗?如果是这样,你能向我解释发生了什么吗?另外,我应该提到它们确实都在运行 x86 CPU。提前致谢 :)

4

1 回答 1

2

参考FreeBSD Developer's handbook,你需要做:

push %eax
mov $1, %eax
push %eax
int $0x80

因为:

  1. 只有系统调用向量通过寄存器传递%eax,所有参数都在堆栈上
  2. FreeBSD 默认系统调用需要堆栈上的一个附加字,这对于内联使用来说是一个虚拟的,int $0x80但是一个返回地址,您可以在其中通过call kernel_entry蹦床进行系统调用(然后可以这样做int $0x80; ret)。

如果您想使用 Linux 约定(regs 中的一些系统调用参数,在手册中称为“替代调用约定”),您必须标记可执行文件,以便系统知道您正在使用 Linux 样式的系统调用。

于 2011-06-23T10:01:08.117 回答