eax
に格納されている番号9を、文字 '9'のASCIIコードポイントに48を追加することで正しく変換しますが、その値をバッファに格納してwrite
と呼ぶのではなく、メモリアドレスとして、そのアドレスからecx
に読み出します。メモリアドレス(9 + 48 =)57は、ヌルポインタの逆参照をキャッチするために予約されたアドレス空間の領域内にあるため、セグメンテーションを取得します。
あなたはこのような何かの代わりに(注:私はインテルのバックasswards構文を使用することを拒否。gcc numbernine.s
でコンパイルし、64ビットの分布に、あなたはgcc -m32 numbernine.s
を使用する必要があります):たい
.data
.align 4
.type buf,@object
.size buf, 2
buf:
.byte 0
.byte 10
.text
.align 4
.globl main
.type main,@function
main:
leal buf,%ecx
movb $9,%al
addb $48,%al
movb %al,(%ecx)
subl $12,%esp
movl $2,8(%esp)
movl %ecx,4(%esp)
movl $1,(%esp)
call write
addl $12,%esp
xorl %eax,%eax
ret
接線をkibitz:代替がない場合に限り、直接システムコールを行います。 Cライブラリがラッパーを提供する場合は、それを使用します。 write
の問題はそれほどありませんが、Cライブラリラッパーが裸のカーネルABIの変更からあなたを守るためにいくらかの長さになるシステムコールがたくさんあります。それ。また、Cライブラリは、sysenter
(または64ビットABIにはsyscall
)を使用する方法とerrno
を設定する方法を知っています。これが私がスタックに物を押して、あなたがしていたものではなくwrite
を呼び出す理由です。
さらに、main
から返すことができるときに、直接システムコールを使用してプロセスを終了するのは愚かです。
私はそれをやってみましたが、動作しません。私はそれがsyscallが文字列のアドレスを含むためにecxを必要とするからだと思う。 – Kevin
バイト0x39(つまりASCII '9')をメモリに格納し、メモリアドレスを 'ecx'に入れる必要があります。これを行うための標準的な方法は、スタックにスペースを割り当てることです(http://en.wikibooks.org/wiki/X86_Disassembly/Functions_and_Stack_Frames#Standard_Entry_Sequenceを参照)。次にlea ecx、[ebp-4]スタック割り当てバッファのアドレス。 –
ああありがとうございます。私はmov ecx、eaxをpush eaxに置き換え、lea ecx、espに置き換えて動作させた。 – Kevin