1
movl %ebx, %esi
movl $.LC1, %edi
movl $0, %eax
call printf

次の asm コードを使用して、EBXレジスタの内容を出力します。私が使うとき

movl $1,%eax
int 0x80

そして、echo $?最初のケースでは正しい答えが得られますが、セグメンテーション違反です。GNU アセンブラーと AT&T 構文を使用しています。この問題を解決するにはどうすればよいですか?

4

2 に答える 2

1

コードから判断すると、おそらく 64 ビット モードです (確認してください)。この場合、ポインタのサイズは 64 ビットです。Linux 上の位置依存の実行可能ファイルmovl $.LC1, %ediは安全であり、コンパイラが使用するものですが、コードを位置に依存せず、下位 32 ビットの外側にあるシンボル アドレスを処理できるようにするには、leaq .LC1(%rip), %rdi.

さらに、次のことを確認してください。

  • rbx関数の値を保持しています
  • スタックポインタは必要に応じて整列されます

このコードは 64 ビットで動作します。

.globl main
main:
    push %rbx
    movl $42, %ebx
    movl %ebx, %esi
    leaq .LC1(%rip), %rdi
    movl $0, %eax
    call printf
    xor  %eax, %eax
    pop  %rbx
    ret

.data
    .LC1: .string "%d\n"
于 2013-01-05T14:06:11.410 に答える
0

編集:Jesterが指摘したように、この回答はx86(32ビット)asmにのみ適用されますが、提供されるサンプルはx86-64の可能性が高くなります。

これは、printfには可変数の引数があるためです。printf呼び出しはスタックを復元しません。自分で復元する必要があります。

あなたの例では、次のように書く必要があります(32ビットアセンブリ):

push %ebx
push $.LC1
call printf
add $8, %esp  // 8 : 2 argument of 4 bytes
于 2013-01-05T06:49:11.777 に答える