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. システム コール ベクトルのみが register 経由で渡され%eax、すべての引数はスタックにあります
  2. FreeBSD のデフォルトの syscall は、スタック上に追加の単語を期待します。これは、インラインで使用するためのダミーですint $0x80が、トランポリンを介して syscall を実行する場合の戻りアドレスになりますcall kernel_entry(その後、実行できますint $0x80; ret)。

Linux 規則 (regs 内のいくつかの syscall 引数、マニュアルでは「Alternative Calling Convention」と呼ばれる) を使用する場合は、Linux スタイルのシステムコールを使用していることをシステムが認識できるように、実行可能ファイルをブランド化する必要があります。

于 2011-06-23T10:01:08.117 に答える