2010-12-15 15 views
0

私はLinux用のアセンブラを習っていますが、このサンプルプログラムでは、write syscallを呼び出して、 'Hello、World!'と表示することになっていますが、segfaultが生成されます。私は宿題ではなく、私の自由な時間に学びます、私はもはや学校に行くことはありません!linux asm x86 production segfault

誰でもこのコードで何か問題が見えることはありますか?

xor eax,eax 
xor ebx,ebx 
xor ecx,ecx 
xor edx,edx 
jmp short string 
code: 
pop  ecx 
mov  bl,1 
mov  dl,13 
mov  al,4 
int  0x80 
dec  bl 
mov  al,1 
int  0x80 
string: 
call code 
db  'Hello, World!' 
+3

私は、あなたの文字列のアドレスを 'ecx'にロードするのは、まれな方法です。 –

+0

segfaultを出力する前にsegfaultを出力するか出力を生成しませんか? –

+0

@Greg:それは位置独立したシェルコードを書いている最も一般的な方法の一つですが、合意しました... –

答えて

1

私はLinuxのアセンブリに非常に慣れていないんだけど、ここでは推測です:

APIを呼び出すときに、あなたが特定の呼び出し規約を使用する必要があります。規約で指定されているものの1つは、API呼び出しで保持されるレジスタのリストです。あなたの場合、エラーはxor ebx, ebxの代わりにdec blを使用しています。入力パラメータとしてblが使用されているため、保存される可能性は非常に低いです。 mov al, 1と同じですが、書く方が安全ですmov eax, 1

そして、私は@Greg Hewgilに同意します。文字列のアドレスを取得するあなたの方法は非常に珍しいです。文字列で位置独立コードを書く一般的な方法は次のとおりです。

... 
call my_print 
db 'hello world!', 0 
... 

my_print: 
pop ecx 
xor edx, edx 
lp: 
cmp byte [ecx + edx], 0 
inc edx 
jne lp 
lea eax, [ecx + edx] 
push eax // return address 
dec edx 
mov eax, 4 
int 0x80 
ret 
+0

あなたの "共通の"方法はOPとは特に違いはありません。あなたはまだデータの直前まで 'jmp'をやっていて、最終的にデータのアドレスをレジスタに取得する' pop'を実行して 'call'を返します。唯一の違いは、そのすべての後にレジスタをどのように使用しているかです。 –

+0

@エヴァン・テラン:違いは、文字列が使用されているところに現れ、長さが自動的に計算されることです。 – ruslik

+0

「\ 0」「自動」を検索するループをほとんど呼び出せませんでした。 –

0

このコードは、64ビットカーネルでコンパイルして実行するとクラッシュする可能性があります。 64ビットのリターンアドレスは32ビットecxレジスタに収まらないので、代わりにrcxをポップする必要があります。さらに、このコードでは32ビットAPIを使用していますが、64ビットカーネルでは使用できない可能性があります。私のブログの投稿:x86-64 assembly on Linuxに記載されているように、代わりに64ビットAPIを使用する必要があります。

2

私のために働きます。ここで私は(ノート、私は32ビットのバイナリを作成するために、余分なフラグを持っているので、私は64ビットマシン上でだ)やったことだ:

TEST.ASM

_start: 
xor eax,eax 
xor ebx,ebx 
xor ecx,ecx 
xor edx,edx 
jmp short string 
code: 
pop  ecx 
mov  bl,1 
mov  dl,13 
mov  al,4 
int  0x80 
dec  bl 
mov  al,1 
int  0x80 
string: 
call code 
db  'Hello, World!' 

コマンド:

$ nasm -felf test.asm -o test.o 
$ gcc -m32 -nostdlib -nostdinc test.o -o test 

警告を出しましたが、これは問題ありません。

/usr/lib/gcc/x86_64-pc-linux-gnu/4.5.1/../../../../x86_64-pc-linux-gnu/bin/ld: warning: cannot find entry symbol _start; defaulting to 0000000008048080 

は、それから私は走った:

$ ./test 

し、それを実際に(改行なし)出力"Hello, World!"。 segfaultはありません。

+0

それは問題だったようです。 – ruslik

関連する問題