2016-04-07 7 views
0

Linux上でテキストファイルから文字列を取り込み、文字列内のすべての文字を1ずつシフトし、printfに出力する32ビットx86 NASMプログラムを作成しようとしています。コンソール。シフトをするのに使われるループ.rot132printfを除いて、ほとんど全てが機能します。 .rot132が呼び出されるたびに、segmentation_fault(コアダンプ)が返されます。私はいつmovを行うと思いますかecx, [eax]何らかのエラーが発生します。どうすればこの部分を克服できますか?アセンブリ言語を変更する入力文字列エラー

;;sddddddddddddddddgsd 

[SECTION .data] ; Section containing initialized data 

WriteCode db "w",0 
OpenCode db "r",0 
Filename db "text.txt",0 
fileFmt: dd "%c\n",10,0 
fileFmt1: dd "%s",10,0 

[SECTION .bss] ; Section containing uninitialized data 
TextLenght EQU 72 ; Define length of a line of text data 
Text resb TextLenght ; Reserve space for disk-based help text line 
BUFSIZE EQU 64 ; Define length of text line buffer 
Buff resb BUFSIZE+5 ; Reserve space for a line of text 

[SECTION .text] ; Section containing code 
;; These externals are all from the glibc standard C library: 
extern fopen 
extern fclose 
extern fgets 
extern fprintf 
extern printf 
extern sscanf 
extern time 

global main ; Required so linker can find entry point 

main: 

diskhelp: 
     mov ebx, Filename ; push file name to ebx 
     push OpenCode ; Push pointer to open-for-read code “r“ 
     push ebx ; Pointer to name of help file is passed in ebx 
     call fopen ; Attempt to open the file for reading 
     add esp,8 ; Clean up the stack 
     cmp eax,0 ; fopen returns null if attempted open failed 
     jne .disk ; Read help info from disk file... 
     ret 

.disk: mov ebx,eax ; Save handle of opened file in ebx 

.rdln: push ebx ; Push file handle on the stack 
     push dword TextLenght ; Limit line length of text read 
     push Text ; Push address of text line buffer 
     call fgets ; Read a line of text from the file 
     add esp,12 ; Clean up the stack 
     ;cmp eax,0 ; A returned null indicates error or EOF 
     ;jle .rot13 ; If we get 0 in eax, close up & return 

     ;push Text ; Push address of help line on the stack 
     ;call printf ; Call printf to display help line 
     ;add esp,4 ; Clean up the stack 

.rot131: ; initial shift and test, this work 
     mov edx, 0 ; our counter 
     mov eax, Text ; move string into eax 
     mov ecx, [eax]; move first char in string into ecx 
     add ecx, 1 ; shift the char up by 1 
     push ecx  ; push to print 
     push fileFmt 
     call printf 
     add esp, 8 ; clear the stack 
     inc edx  ; increase the counter 

.rot132: 
     inc eax  ; shift address of eax into next char 
     mov ecx, [eax] ; move the char into ecx, replace old char; error ?? 
     add ecx, 1  ; shift the char by 1 
     push ecx  ; print 
     push fileFmt 
     call printf 
     add esp, 8  ; clear the stack 
     inc edx   ;incrase counter 
     cmp edx,4  ; stop loop after edx = 4 
     jne .rot132 


     push ebx ; Push the handle of the file to be closed 
     call fclose ; Closes the file whose handle is on the stack 
     add esp,4 ; Clean up the stack 

     ret ; Go home 

GDBデバッグ:.rot132を分解:

0x08048559 <+0>:  inc %eax 
    0x0804855a <+1>:  mov (%eax),%ecx 
    0x0804855c <+3>:  add $0x1,%ecx 
    0x0804855f <+6>:  push %ecx 
    0x08048560 <+7>:  push $0x804a035 
    0x08048565 <+12>: call 0x80483b0 <[email protected]> 
    0x0804856a <+17>: add $0x8,%esp 
    0x0804856d <+20>: inc %edx 
    0x0804856e <+21>: cmp $0x4,%edx 
    0x08048571 <+24>: jne 0x8048559 <rot132> 
    0x08048573 <+26>: push %ebx 
    0x08048574 <+27>: call 0x80483d0 <[email protected]> 
    0x08048579 <+32>: add $0x4,%esp 
    0x0804857c <+35>: ret 
    0x0804857d <+36>: xchg %ax,%ax 
    0x0804857f <+38>: nop 
+2

デバッガでは、エラーが発生したときに表示される内容は何ですか? –

+1

あなたはどのOSを使用していますか? Linux/OSX/BSD/Windows? –

+0

申し訳ありませんが、現在Linuxでnasm x86を使用しています。 –

答えて

1

db、ないddにする必要がありfileFmt。ダブルワード文字を定義しています。

このコードは、コンパイラが生成したコードほど良くないことに注意してください。プロファイルの最上部で明白なCPUのボトルネックとなるクリティカルループについては、アセンブリ言語を悩ますだけで、すでに良いアルゴリズムを使用しています。

例は、行列乗算です。これはembarassingly parallelです。したがって、コンパイラにSSEのようなベクトル拡張を使用するなど、操作を実行するための最も効率的な手段を使用するように強制することは、しばしば有益です。

コンパイラは非常に優れているため、SSEやAVX組み込み関数などのコンパイラがデータフローやレジスタの割り当てを気にせず、命令自体に集中することができます。

マイケル・ペッチの良いコメント:コールはクローバーに許可されますeaxecxedxです。あなたはそれらが保存されると信じることができますebxesiediebpesp。つまり、変数にはecxedxの使用を止め、ebxediesiebpのように保存されているものを使用する必要があります。

+0

まだセグメント化エラーが発生します。私はそれがエラーを消え去るので、私はそれがmovエックス、[eax]をしなければならないと確信しています。私はなぜmov ecx、[eax]がエラーを起こすのか分かりません。 –

+0

問題のリストが最新のものである場合でも、.rot132ループのprintf呼び出し中に "eax"値は保持されません。だから、あなたはいくつかの偽のメモリにアクセスし、したがってsegfaultingします。ところで、mov ecx、[eax]はメモリから4バイトをフェッチしているので、もしあなたのTextバッファがmemページに収まるならば、最後の3バイトにアクセスするとsegfaultになります。大丈夫です)。むしろ、正しい "movzx ecx、byte ptr [eax]を使用するべきです(私はNASM構文についてはわかりません)。 – Ped7g

+0

@ Ped7g 'byte ptr'は* MASMism/TASMism *になります。 _NASM_は 'movzx ecx、byte [eax]'( 'ptr'だけを削除します)です。 –

関連する問題