• 締切済み

メモリデータ比較中にハング

メモリデータ比較中にハング A領域のデータとB領域のデータを先頭から比較するプログラムをアセンブラで組んでおります。 しかしかなりの頻度でプログラムがハングし、困っております。 ソースを眺めていても、どこが悪いのかわかりません。ハングの原因をうまく調べる方法はあるでしょうか? 動作環境:MS-DOS アセンブラ:MASM32 MOV ECX, srcAddr;Aのメモリアドレス PUSH ECX POP ESI MOV ECX, dstAddr;Bのメモリアドレス PUSH ECX POP EDI MOV ECX, CmpByte;比較するバイト数(比較するのは100000Hexバイト) XOR EAX, EAX CALL ENTER_PROTECT;プロテクトモードに移行 CALL GET_SORC_SEL;SORC_SELのBASE AddressとLimitを変更 CALL GET_DEST_SEL;DEST_SELのBASE AddressとLimitを変更 ; DWORD単位で比較するので2で割る SHR ECX, 2 @@compare: CLD ;CMPS*でのESI,EDIの変化を増加方向に @@cmp4: CMPSD DS:[ESI], ES:[EDI] ;4Byteずつ比較 jne @@err4 dec ECX jnz @@cmp4 ; 4で割った余り分のチェック MOV ECX, CmpByte AND ECX, 3 or ecx, ecx jz @@exit jmp @@cmp1 @@err4: ; 1Byteずつチェックしてコンペアエラーしたオフセットを割り出す LEA ESI,[ESI-4] ; コンペアエラー前のオフセットに戻す LEA EDI,[EDI-4] shl ecx, 2 @@cmp1: ;1Byteずつ比較 CMPSB DS:[ESI], ES:[EDI] jne @@exit dec ECX jnz @@cmp1 @@exit: ; コンペアしたByte数を計算(EAX <- CmpByte - ECX) MOV EAX, CmpByte SUB EAX, ECX PUSH EAX CALL FREE_SORC_SEL CALL FREE_DEST_SEL CALL LEAVE_PROTECT POP AX POP BX MOV DX, BX RET _MemCmp2 ENDP

みんなの回答

noname#159916
noname#159916
回答No.1

随分前に少し触れただけでうろ覚えですが。 ES や DS はどこで定義されるんでしょう? プロテクトモードだと ディスクリプタテーブルなどもきちんと設定しないと 物理アドレスを決められないし、エクセプションが発生すると 思います。 デフォルトでなんとかに設定されてる、なら不要なんでしょうけど。

TatsCat
質問者

お礼

ありがとうございます。 作った方がいなくなり、代わりにバグを修正することになり、 困っていました。ディスクリプタテーブルは設定されていますが、 設定方法を確認してみます。

関連するQ&A

  • これらの文を意味のわかる分にしてください

    アドレス          ダンプ    逆アセコード 00551A90 31C9 XOR ECX,ECX 00551A92 51 PUSH ECX 00551A93 E8 68575000 CALL 00A57200 00551A98 59 POP ECX 00551A99 41 INC ECX 00551A9A 83F9 02 CMP ECX,2 00551A9D 75 F3 JNZ SHORT 00551A92 00551A9F 31C0 XOR EAX,EAX 00551AA1 C2 0400 RETN 4 00551AA4 90 NOP 00551AA5 ゞ 00551AA6 ゞ 00551AA7 ゞ 00551AA8 ゞ 00551AA9 90 NOP 00551AAA 8B4424 04 MOV EAX,[ESP+4] 00551AAE 8B48 04 MOV ECX,[EAX+4] 00551AB1 8B10 MOV EDX,[EAX] 00551AB3 8B40 08 MOV EAX,[EAX+8] 00551AB6 51 PUSH ECX 00551AB7 52 PUSH EDX 00551AB8 50 PUSH EAX 00551AB9 E8 12BB2B00 CALL 0080D5D0 00551ABE 83C4 0C ADD ESP,C 00551AC1 33C0 XOR EAX,EAX 00551AC3 C2 0400 RETN 4

  • アセンブリ言語の宿題がわかりません。

    爆弾を解除するプログラムです。exeファイルしか与えられていません。 phase1から5まであり、それぞれにインプットを求められ、正しいインプット(解除コード)を入力すると解除できます。 間違ったコードを入力すると爆発してしまいます。1,2は解けましたが、3で躓きました。objdumpしてみて、あるstring(恐らくglobal定数)と同じインプットをすれば解除できると踏んだのですが、どうしてもその特定のstringがわかりません。 以下にobjdumpした内の一部を載せておきました。都合上最小限のコードだけ載せざるを得ませんでしたので、 下記URLに、exeファイル、逆アセンブルファイル、phase1,2のanswerをアップロードしております。お時間があれば是非ご協力をお願いします。 環境 OS:ubuntu 9.04 デバッガ:Gnu DeBugger 08048424 <_IO_getc@plt>: 8048424: ff 25 10 a0 04 08 jmp *0x804a010 804842a: 68 20 00 00 00 push $0x20 804842f: e9 a0 ff ff ff jmp 80483d4 <_init+0x18> 08048723 <phase_3_of_5>: 8048723: 55 push %ebp 8048724: 89 e5 mov %esp,%ebp 8048726: 57 push %edi 8048727: 56 push %esi 8048728: 53 push %ebx 8048729: 83 ec 1c sub $0x1c,%esp 804872c: a1 30 a0 04 08 mov 0x804a030,%eax 8048731: 89 04 24 mov %eax,(%esp) 8048734: e8 eb fc ff ff call 8048424 <_IO_getc@plt> 8048739: bb 00 00 00 00 mov $0x0,%ebx 804873e: 8d 75 e6 lea -0x1a(%ebp),%esi 8048741: eb 04 jmp 8048747 <phase_3_of_5+0x24> 8048743: 88 44 33 ff mov %al,-0x1(%ebx,%esi,1) 8048747: a1 30 a0 04 08 mov 0x804a030,%eax 804874c: 89 04 24 mov %eax,(%esp) 804874f: e8 d0 fc ff ff call 8048424 <_IO_getc@plt> 8048754: 83 f8 0a cmp $0xa,%eax 8048757: 74 06 je 804875f <phase_3_of_5+0x3c> 8048759: 43 inc %ebx 804875a: 83 fb 0f cmp $0xf,%ebx 804875d: 75 e4 jne 8048743 <phase_3_of_5+0x20> 804875f: c6 45 f3 00 movb $0x0,-0xd(%ebp) 8048763: 8d 75 e6 lea -0x1a(%ebp),%esi 8048766: bf e4 8b 04 08 mov $0x8048be4,%edi 804876b: b9 0d 00 00 00 mov $0xd,%ecx 8048770: fc cld 8048771: f3 a6 repz cmpsb %es:(%edi),%ds:(%esi) 8048773: 0f 97 c2 seta %dl 8048776: 0f 92 c0 setb %al 8048779: 38 c2 cmp %al,%dl 804877b: 74 0c je 8048789 <phase_3_of_5+0x66> 804877d: c7 04 24 03 00 00 00 movl $0x3,(%esp) 8048784: e8 31 fe ff ff call 80485ba <explode> 8048789: 83 c4 1c add $0x1c,%esp 804878c: 5b pop %ebx 804878d: 5e pop %esi 804878e: 5f pop %edi 804878f: 5d pop %ebp 8048790: c3 ret

  • アセンブリ言語について。

    これが何をしているのか教えていただけないでしょうか?すみません。 これの事です。 (機械語データ) (アセンブリ言語) b8 57 61 6b 61 mov $0x616b6157,%eax 53 push %ebx 50 push %eax ba 04 00 00 00 mov $0x4,%edx bb 01 00 00 00 mov $0x1,%ebx b8 04 00 00 00 mov $0x4,%eax 89 e1 mov %esp,%ecx cd 80 int $0x80 58 pop %eax 31 c0 xor %eax,%eax 5b pop %ebx c3 ret

  • 機械語とアセンブリ言語について。

    (機械語データ) (アセンブリ言語) b8 57 61 6b 61 mov $0x616b6157,%eax 53 push %ebx 50 push %eax ba 04 00 00 00 mov $0x4,%edx bb 01 00 00 00 mov $0x1,%ebx b8 04 00 00 00 mov $0x4,%eax 89 e1 mov %esp,%ecx cd 80 int $0x80 58 pop %eax 31 c0 xor %eax,%eax 5b pop %ebx c3 ret こちらのアセンブリ言語の命令がわかるおすすめの書籍を知らないでしょうか? 教えていただけないでしょうか?すみません。

  • 機械語とアセンブリ言語について。

    (機械語データ) (アセンブリ言語) b8 57 61 6b 61 mov $0x616b6157,%eax 53 push %ebx 50 push %eax ba 04 00 00 00 mov $0x4,%edx bb 01 00 00 00 mov $0x1,%ebx b8 04 00 00 00 mov $0x4,%eax 89 e1 mov %esp,%ecx cd 80 int $0x80 58 pop %eax 31 c0 xor %eax,%eax 5b pop %ebx c3 ret で、右側のアセンブリ言語のニーモニックとオペランドについて解説していただけないでしょうか?すみません。

  • アセンブリ言語の質問です

    「 100人分の試験点数がある。 一人分のデータは32bit 符号無し整数でそれが連続して格納されている.先頭のアドレスがEAXで与えられる時,全員の点数の合計をEAXに入れて戻るようなサブルーチンをアセンブリ言語で書きなさい。 • loop unrollingを使用して,ループ内容を4倍に展開して,条件分岐数を減らすこと • 他のレジスタの値は保存すること • 合計点はEAXレジスタに十分納まるものとする。 • 次のような命令を使ってよい。 ADD EAX, [EBX] 」 というような問題が出て自分で解答を作ってみたのですがこれでよいのでしょうか?詳しい方ご検討よろしくお願いいたします。 PUSH EBX(EBXをスタックにおいておく) PUSH ECX(ECXをスタックにおいておく) MOV ECX 25(ECXに25を代入。4回の操作を25回すれば100回になるからである。) label0:ADD EAX [EAX] ([EAX]をEAXに加算) ADD EAX [EAX+1]([EAX+1]をEAXに加算) ADD EAX [EAX+2]([EAX+2]をEAXに加算) ADD EAX [EAX+3]([EAX+3]をEAXに加算) MOV [EAX] [EAX+4]([EAX]を[EAX+4]に移動させる) EBX=EBX+1 (EBXはこのループを何回やったか、という数) CMP ECX EBX(25とEBXを比べる) JNZ:label0(比べてEBXが25になってないならば繰り返す。25になったら終了。) POP EBX(EBXをスタックから戻す) POP ECX(EBXをスタックから戻す)

  • VisualStudio2008の最適化について

    VisualStudio2008の最適化について こんにちは。 質問させてください。 現在VisualStudioでとある処理を書きました。 わかりやすく以下のコードを書いたとします。 #include <stdio.h> #include <windows.h> #pragma comment ( lib, "winmm" ) int main() {   DWORD t = timeGetTime();   int sum=0;   int i=0;   for( i=0;i<0x7fffffff;++i )     ++sum;   t = timeGetTime() - t;   printf( "time -> %d\n", t );   return 0; } 今回は単純にfor文の時間を計測したいとします。 上記コードをReleaseモード実行速度重視 (/O2)でコンパイルし、実行すると出力は必ず time -> 0 と出力されます。 上記コードをReleaseモード実行速度重視 (/O2)でコンパイルしアセンブリとして出力したものです。 CONSTSEGMENT ??_C@_0M@DAGCMHCE@time?5?9?$DO?5?$CFd?6?$AA@ DB 'time -> %d', 0aH, 00H ; `string' push esi mov esi, DWORD PTR __imp__timeGetTime@0 push edi call esi mov edi, eax call esi sub eax, edi push eax push OFFSET ??_C@_0M@DAGCMHCE@time?5?9?$DO?5?$CFd?6?$AA@ call DWORD PTR __imp__printf add esp, 8 pop edi xor eax, eax pop esi ret 0 アセンブリコードを見るとするとint sumはコード中でインクリメントされるだけで他に使用されないので、最適化によって削除されてしまっているようです。 この、時間を計測したいところだけ適度に最適化させつつ、処理が残るようにするような命令はありませんでしょうか? pragmaでかこったりするだけで処理が消されない程度に最適化されるとうれしいのですが・・・ よろしくお願いします。 /*   VisualaStudio 2008 academic Edition   今回のテストケースではsumの値もコンソールに出力すれば最適化で消されずに済むのですが最適化の計算によってforループは削除され、代わりに即値(0x7fffffff)がそのまま表示されるように最適化されてしまいます。   ですので今回は   ・使用した変数を使用するように書き換える   ・最適化で消されないようにコードを記述しなおす   ・inlineアセンブラで最適化させない   といった解決策以外でよろしくお願いします。 */

  • 機械語に直すことについて。

    (機械語データ) (アセンブリ言語) b8 57 61 6b 61 mov $0x616b6157,%eax 53 push %ebx 50 push %eax ba 04 00 00 00 mov $0x4,%edx bb 01 00 00 00 mov $0x1,%ebx b8 04 00 00 00 mov $0x4,%eax 89 e1 mov %esp,%ecx cd 80 int $0x80 58 pop %eax 31 c0 xor %eax,%eax 5b pop %ebx c3 ret これのintと movとxor の機械語が分かりません。後、retの機械語が、farなのかnearなのかも分かりません。教えていただけないでしょうか?すみません。

  • アセンブリ言語について。

    >2進数の羅列では人間にはあまりに読み書きしにくいからです。 >それを命令単位に区切って、英単語を元にした名前を与えたのが、 >アセンブリ言語です。 ニーモニックとは、その命令の名前の事です。 簡潔に要点がまとまっている、すばらしい説明ですね。その通りです。 これで理解できないなら、追加の説明のしようがありません。 (なお、このように、他人の発言は引用符を付けて引用すると、わかりやすくなります。是非そうしてください。) まあ具体例を挙げるならこんな感じ。 (機械語データ) (アセンブリ言語) b8 57 61 6b 61 mov $0x616b6157,%eax 53 push %ebx 50 push %eax ba 04 00 00 00 mov $0x4,%edx bb 01 00 00 00 mov $0x1,%ebx b8 04 00 00 00 mov $0x4,%eax 89 e1 mov %esp,%ecx cd 80 int $0x80 58 pop %eax 31 c0 xor %eax,%eax 5b pop %ebx c3 ret 人間がCPUを直接動かすプログラムを書こうとするとき、アセンブリ言語を使って書きます(右側の部分)。 mov $0x616b6157,%eax push %ebx push %eax mov $0x4,%edx mov $0x1,%ebx mov $0x4,%eax mov %esp,%ecx int $0x80 pop %eax xor %eax,%eax pop %ebx ret そしてこれをアセンブルすると、1対1対応した機械語のデータ列が出来ます。 それが b8 57 61 6b 61 53 50 ba 04 00 00 00 bb 01 00 00 00 b8 04 00 00 00 89 e1 cd 80 58 31 c0 5b c3 この部分。 機械語には改行なんてありませんから、実際は一連の b8 57 61 6b 61 53 50 ba 04 00 00 00 bb 01 00 00 00 b8 04 00 00 00 89 e1 cd 80 58 31 c0 5b c3 と言うデータ列になります。 これをCPUが実行していきます。 相当熟練した人で無ければ、このデータ列を見るだけでプログラム構造を理解する、というわけに行きません。 なので、人間が機械語レベルでプログラミングする際には、アセンブリ言語を使います。 ※この回答のプログラムはこちらから引用しました。 >31バイトでつくるアセンブラプログラミング アセンブラ短歌の世界 >https://book.mynavi.jp/support/pc/4946/c01_assembra.pdf で、機械語データは、なぜ、0と 1だけではないのでしょうか?教えていただけないでしょうか?すみません。

  • システムコールについて。

    アセンブリ言語で、int $0x80はシステムコールと言われていますが、Linuxを知らないとわかりません。システムコールはアプリとカーネルのインターフェースです。 x86 Linux 32bitのシステムコールの呼び出しは int 0x80です。 システムコールはEAXに格納されている数値でいろいろな処理ができます。 https://www.mztn.org/lxasm64/x86_x64_table.html を見ていただくとWRITEのsyscall#は4です。 mov $0x4,%eax でeaxに4を入れているので画面に出力したいのだとわかります。 WRITEの第2引数は画面に出力したい文字列が格納されているアドレスでECXに格納します。 mov %esp,%ecx とスタックポインターのアドレスをecxに入れています。 ESPは push eax でEAXに格納されている$0x616b6157(Waka)がスタックに退避しています。 WRITEの第3引数は文字数です。文字数はEDXに格納します。 mov $0x4,%edx と4が入っているので文字数は4です。 このプログラムを実行させると画面にWakaと表示して元の画面に戻ります。そのためのRETです。 C言語で書けばたった1行。 write(1,"Waka",4) これについて詳しく教えていただけないでしょうか?すみません。

専門家に質問してみよう