movl %ebx, %esi
movl $.LC1, %edi
movl $0, %eax
call printf
次の asm コードを使用して、EBXレジスタの内容を出力します。私が使うとき
movl $1,%eax
int 0x80
そして、echo $?
最初のケースでは正しい答えが得られますが、セグメンテーション違反です。GNU アセンブラーと AT&T 構文を使用しています。この問題を解決するにはどうすればよいですか?
movl %ebx, %esi
movl $.LC1, %edi
movl $0, %eax
call printf
次の asm コードを使用して、EBXレジスタの内容を出力します。私が使うとき
movl $1,%eax
int 0x80
そして、echo $?
最初のケースでは正しい答えが得られますが、セグメンテーション違反です。GNU アセンブラーと AT&T 構文を使用しています。この問題を解決するにはどうすればよいですか?
コードから判断すると、おそらく 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"
編集:Jesterが指摘したように、この回答はx86(32ビット)asmにのみ適用されますが、提供されるサンプルはx86-64の可能性が高くなります。
これは、printfには可変数の引数があるためです。printf呼び出しはスタックを復元しません。自分で復元する必要があります。
あなたの例では、次のように書く必要があります(32ビットアセンブリ):
push %ebx
push $.LC1
call printf
add $8, %esp // 8 : 2 argument of 4 bytes