MOVニーモニックを使用して文字列をMASMのメモリレジスタにロード/コピーする場合、文字は逆の順序で格納されますか?

2
Joachim Rives 2019-08-09 10:12.

MOV命令を使用して文字列をレジスタにコピーすると、文字列が逆の順序で格納されるかどうかを知りたいです。MASMが文字列を単語以上(dw以上のサイズ)として定義された変数に格納する場合、文字列は逆の順序で格納されることを学びました。文字列をレジスタにコピーしても同じことが起こりますか?

この質問(SCAS命令とMASM 32の変数への文字列と文字の割り当てについて)に基づいて、私は次のことを想定しました。

  1. MASMが文字列を変数にロードすると、逆の順序でロードされます。つまり、文字列の最後の文字は、文字列変数の最下位のメモリアドレス(先頭)に格納されます。これは、次のように変数strを割り当てることを意味しますstr dd "abc"。MASMは文字列を「cba」として格納します。これは、「c」が最小のメモリアドレスにあることを意味します。
  2. 変数をstr db "abc"MASMとして定義すると、str文字の配列として扱われます。配列インデックスをメモリアドレスのと一致させようとするとstr、MASMは「a」を最小のメモリアドレスのに格納しますstr
  3. デフォルトでは、SCASおよびMOVS命令は、宛先文字列、つまりEDIレジスタに格納されている文字列の先頭(最低)アドレスから実行されます。実行前に操作するメモリアドレスに「後入れ先出し」ルールを「ポップ」または適用しません。
  4. MASMは、メモリレジスタへの文字配列と文字列を常に同じ方法で処理します。文字配列「a」、「b」、「c」をEAXに移動することは、「abc」をEAXに移動することと同じです。

arLetters文字「a」、「b」、および「c」を含むバイト配列をstrLettersを使用してダブルワード変数に転送するMOVSDと、文字はstrLetters逆にコピーされる、つまり「cba」として格納されると思います。使用するmov eax, "abc"場合、文字も逆の順序で保存されますか?

以下のコードは、終了する前にゼロフラグを設定します。

.data?
strLetters dd ?,0

.data
arLetters db "abcd"

.code

start:
mov ecx, 4
lea esi, arLetters
lea edi, strLetters
movsd
;This stores the string "dcba" into strLetters.

mov ecx, 4
lea edi, strLetters
mov eax, "dcba" 
repnz scasd
jz close
jmp printer
;strLetters is not popped as "abcd" and is compared as "dcba".

printer:
print "No match.",13,10,0
jmp close

close:
push 0
call ExitProcess

end start

MASMは文字列の移動を変数への文字列の割り当てとは異なるレジスタに処理するため、文字列「dcba」は「そのまま」EAXに格納されると思います。「d」はEAXの最小メモリアドレスにあります。MASMは、 『(ABCD『)strLettersがポップされた場合、文字列が正しい順序で放出/ emmittedされることを保証するために、』DCBA「としてstrLettersに』 '、「B」、' C「D」にコピー。場合REP MOVSB指示の代わりに使用されたMOVSD場合、strLettersには「abcd」が含まれ、「dcba」としてポップ/出力されます。ただし、MOVSD使用され、SCASまたはMOVS命令は実行前に文字列をポップしないため、上記のコードはゼロフラグを設定する必要があります。正しい?

2 answers

5
Ross Ridge 2019-08-10 02:37.

MASMが16ビット以上の整数を期待するコンテキストでは文字列を使用しないでください。MASMは、メモリに格納されたときに文字の順序を逆にする方法でそれらを整数に変換します。これは混乱を招くため、これを回避し、DBディレクティブで文字列のみを使用することをお勧めします。これは期待どおりに機能します。文字を超える文字列を即値として使用しないでください。

メモリにはバイトオーダーがありますが、レジスタにはありません

レジスターにはアドレスがなく、レジスター内のバイトの順序について話すことは無意味です。32ビットx86CPUでは、EAXなどの汎用レジスタは32ビット整数値を保持します。32ビット値は概念的に4バイトに分割できますが、レジスタ内にある間は、バイトに意味のある順序はありません。

32ビット値がメモリに存在する場合にのみ、それらを構成する4バイトにアドレスがあり、順序があります。x86 CPUはリトルエンディアンのバイト順序を使用するため、4バイトの最下位バイトが最初のバイトになります。最も重要な部分が最後のバイトになります。x86は、16ビット以上の値をメモリとの間でロードまたは格納する場合は常に、リトルエンディアンのバイトオーダーを使用します。(例外は、値のロードおよび格納時に特にビッグエンディアンのバイト順序を使用するMOVBE命令です。)

したがって、このプログラムを検討してください。

    .MODEL flat

    .DATA
db_str  DB  "abcd"
dd_str  DD  "abcd"
num DD  1684234849

    .CODE
_start: 
    mov eax, "abcd"
    mov ebx, DWORD PTR [db_str]
    mov ecx, DWORD PTR [dd_str]
    mov edx, 1684234849
    mov esi, [num]
    int 3

    END _start

組み立ててリンクすると、次のようなバイトシーケンスに変換されます。

.text section:
  00401000: B8 64 63 62 61 8B 1D 00 30 40 00 8B 0D 04 30 40  ,[email protected]@
  00401010: 00 BA 61 62 63 64 8B 35 08 30 40 00 CC           .º[email protected]
  ...
.data section:
  00403000: 61 62 63 64 64 63 62 61 61 62 63 64              abcddcbaabcd

(Windowsでは、.dataセクションは通常.text、メモリ内のセクションの後に配置されます。)

DBとDDは文字列の扱いが異なります

だから我々は、DBとDDディレクティブ、どれがラベルされたことがわかりますdb_strdd_str、同じ文字列をバイトの二つの異なるシーケンスを生成します"abcd"。最初のケースでは、MASMは、我々は、61H、62H、63H、及び64Hを期待するであろうことのASCII値をバイトのシーケンスを生成しabc、およびdそれぞれ。以下のためのdd_strバイトの順序が逆になっても。これは、DDディレクティブが32ビット整数をオペランドとして使用するため、文字列を32ビット値に変換する必要があり、変換の結果がメモリに格納されると、MASMは文字列内の文字の順序を逆にすることになります。

メモリ内では、文字列と数値はどちらも単なるバイトです

また、ラベルが付けられたDDディレクティブnumも、DBディレクティブと同じバイトシーケンスを生成したことに気付くでしょう。実際、ソースを見ずに、最初の4バイトが文字列であり、最後の4バイトが数値であると判断する方法はありません。プログラムがそれらをそのように使用する場合にのみ、それらは文字列または数字になります。

(10進値1684234849がDBディレクティブによって生成されたものと同じシーケンスバイトに変換された方法はあまり明白ではありません。これはすでに32ビット値であり、MASMによってバイトシーケンスに変換する必要があります。当然のことながら、アセンブラはしたがって、CPUが使用するのと同じリトルエンディアンのバイト順序を使用します。つまり、最初のバイトは1684234849の最下位部分であり、ASCII文字a(1684234849%256 = 97 = 61h)と同じ値になります。は数値の最も重要な部分であり、たまたまd(1684234849/256/256/256 = 100 = 64h)のASCII値です。

即時はDDと同じように文字列を扱います

.text逆アセンブラでセクションの値を詳しく見ると、そこに格納されているバイトのシーケンスがCPUによって実行されたときに命令としてどのように解釈されるかがわかります。

  00401000: B8 64 63 62 61     mov         eax,61626364h
  00401005: 8B 1D 00 30 40 00  mov         ebx,dword ptr ds:[00403000h]
  0040100B: 8B 0D 04 30 40 00  mov         ecx,dword ptr ds:[00403004h]
  00401011: BA 61 62 63 64     mov         edx,64636261h
  00401016: 8B 35 08 30 40 00  mov         esi,dword ptr ds:[00403008h]
  0040101C: CC                 int         3

ここで確認できるのは、MASMmov eax, "abcd"が、dd_strDDディレクティブの場合と同じ順序で、命令の即値を構成するバイトを格納したことです。メモリ内の命令の直接部分の最初のバイトは64hで、ASCII値はd。です。その理由は、32ビットのデスティネーションレジスタでは、このMOV命令が32ビットのイミディエートを使用するためです。つまり、MASMは文字列を32ビット整数に変換する必要があり、dd_str。の場合と同じようにバイトの順序を逆にすることになります。MASMmov ecx, 1684234849は、同じ番号を使用したDDディレクティブで行ったのと同じ方法で、イミディエートとして指定された10進数も処理します。32ビット値は同じリトルエンディアン表現に変換されました。

メモリ内では、命令も単なるバイトです

また、逆アセンブラが、これら2つの命令のイミディエートに16進値を使用するアセンブリ命令を生成したことにも気付くでしょう。CPUと同様に、アセンブラには、即値が文字列と10進数であると想定されていることを知る方法がありません。これらはプログラム内の単なるバイトシーケンスであり、(オペコードB8hおよびB9hからの)32ビットの即値であることがわかっているため、より適切な代替値がないため、32ビットの16進値として表示されます。 。

レジスタの値はメモリの順序を反映しています

デバッガーでプログラムを実行し、ブレークポイント命令(int 3)に達した後にレジスターを検査することにより、実際にレジスターに何が入ったかを確認できます。

eax=61626364 ebx=64636261 ecx=61626364 edx=64636261 esi=64636261 edi=00000000
eip=0040101c esp=0018ff8c ebp=0018ff94 iopl=0         nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
image00000000_00400000+0x101c:
0040101c cc              int     3

これで、最初と3番目の命令が他の命令とは異なる値をロードしたことがわかります。これらの2つの命令はどちらも、MASMが文字列を32ビット値に変換し、メモリ内の文字の順序を逆にする場合を含みます。レジスタダンプは、メモリ内のバイトの順序が逆になると、異なる値がレジスタにロードされることを確認します。

しかし実際には、レジスタにはバイト順序がありません

ここで、上記のレジスタダンプを見て、EAXとECXのみが正しい順序であり、ASCII値がa最初に61時間、ASCII値がd最後に64時間であると考えているかもしれません。MASMがメモリ内の文字列の順序を逆にすると、実際には文字列が正しい順序でレジスタにロードされます。しかし、前に言ったように、レジスタにはバイト順序はありません。数値61626364は、読み取り可能な文字のシーケンスとして値を表示するときに、デバッガーが値を表す方法です。61ナンバリングシステムは数字の最も重要な部分を左側に配置し、左から右に読み取るため、最初の部分になるため、文字はデバッガーの表現の最初に来ます。ただし、前にも述べたように、x86 CPUはリトルエンディアンです。つまり、最も重要でない部分がメモリの最初に来るということです。つまり、メモリの最初のバイトがレジスタ内の値の最下位部分になります。これは、番号システムで数値の最下位部分になるため、デバッガによって数値の右端の2桁の16進数として表示されます。

言い換えると、x86 CPUはリトルエンディアンであり、最初は最下位ですが、番号付けシステムはビッグエンディアンであり、最上位であるため、16進数は、実際にメモリに格納されている方法とは逆の順序でバイト単位で表示されます。

「文字列」をコピーするだけでは順序は変わりません

また、文字列をレジスタにロードすることは、概念的に行われることだけであることも、今では明らかになっているはずです。文字列はアセンブラによってバイトシーケンスに変換され、32ビットレジスタにロードされると、メモリ内でリトルエンディアンの32ビット整数として扱われます。レジスタ内の32ビット値がメモリに格納されると、32ビット値はリトルエンディアン形式で値を表すバイトシーケンスに変換されます。CPUにとって、文字列は、メモリとの間でロードおよび保存される32ビット整数です。

つまり、サンプルプログラムでEAXにロードされた値が、のようなものでメモリに格納されているmov [mem], eax場合、に格納されている4バイトmemは、のイミディエートを構成するバイトに表示されているのと同じ順序になりますmov eax, "abcd"。これは、MASMが即時を構成するバイトにそれらを配置したのと同じ逆の順序(64h、63h、62h、61h)です。

しかし、なぜ?私は知らない、ただそれをしないでください

MASMが文字列を32ビット整数に変換するときに文字列の順序を逆にする理由についてはわかりませんが、ここでの教訓は、文字列を整数に変換する必要があるイミディエートまたはその他のコンテキストとして使用しないことです。アセンブラは、文字列リテラルを整数に変換する方法に一貫性がありません。(Cコンパイラが文字リテラル'abcd'を整数に変換する方法でも同様の問題が発生します。)

SCASDとMOVSDは特別ではありません

SCASDまたはMOVSDインストルメントでは特別なことは何も起こりません。SCASDは、EDIが指す4バイトを32ビットのリトルエンディアン値として扱い、名前のない一時レジスタにロードし、一時レジスタをEAXと比較してから、DFフラグに応じてEDIに4を加算または減算します。MOVSDは、ESIが指すメモリ内の32ビット値を名前のない一時レジスタにロードし、EDIが指す32ビットメモリ位置の一時レジスタを格納してから、DFフラグに従ってESIとEDIを更新します。(バイトが32ビット値として使用されることはないため、MOVSDのバイト順序は重要ではありませんが、順序は変更されません。)

SCASDまたはMOVSDをFIFOまたはLIFOとは考えようとはしません。最終的には、それらの使用方法に依存するからです。MOVSDは、LIFOスタックと同じようにFIFOキューの実装の一部として簡単に使用できます。(これをPUSHおよびPOPと比較してください。これらは、理論的にはFIFOまたはLIFOデータ構造の実装の一部として独立して使用できますが、一緒に使用できるのはLIFOスタックの実装のみです。)

3
Peter Cordes 2019-08-10 10:16.

MASMの動作の詳細については、@ RossRidgeの回答を参照してください。この回答は、MASMだけを気にしている場合は混乱するかもしれないNASMと比較しています。


mov ecx, 4と一緒に使用すると、4つのdword = 16バイトになりますrepne scasd

より簡単なのは、を省略repして使用することscasdです。

またはさらに簡単cmp dword ptr [strLetters], "dcba"です。

マシンコードのイミディエートを見ると、メモリ内でデータと同じ順序である場合、どちらもリトルエンディアンの32ビット整数として扱われるため、等しいと比較されます。(x86命令エンコーディングはリトルエンディアンのイミディエートを使用するため、x86のデータロード/ストアエンディアンと一致します。)

はい、MASMの"dcba"場合、文字列を整数定数として使用する場合は、必要なバイト順序を取得する必要があるようです。MASMは最初の文字を「最上位」として扱い、最後に32ビットのイミディエートを配置するためです。


NASMとMASMはここでは大きく異なります。NASMでは、メモリ内でmov dword [mem], 'abcd'生成'a', 'b', 'c', 'd'します。つまり、一度に1バイトずつメモリの順序がソースの順序と一致します。NASMの文字定数を参照してください。複数文字の定数は、ソース順の文字列バイトを使用して、32ビットのリトルエンディアンイミディエートで単純に右寄せされます。

例えば

objdump -d -Mintel disassembly
   c7 07 61 62 63 64       mov    DWORD PTR [rdi], 0x64636261

NASMソース:mov dword [rdi], "abcd"
MASMソース:mov dword ptr [rdi], "dcba"
GASソース:複数文字の文字列リテラルではAFAIKは使用できません。あなたは次のようなことをすることができます$'a' + ('b'<<8) + ...

のオペランドを除いて、MASMで複数文字の文字列リテラルを回避するというRossの提案に同意しdbます。イミディエートとして適切な複数文字リテラルが必要な場合は、NASMまたはEuroAssembler(https://euroassembler.eu/eadoc/#CharNumbers)


また、使用していないjcc jmpだけ使用し、je closeフォールスルーするかではありません。

(あなたは、通常の脳死のイディオムを避けjccましたjmp。ここでは、あなたjzは正気で、jmp完全に冗長であり、次の命令にジャンプします。)

Related questions

MORE COOL STUFF

Reba McEntire は、彼女が息子の Shelby Blackstock と共有する「楽しい」クリスマスの伝統を明らかにしました:「私たちはたくさん笑います」

Reba McEntire は、彼女が息子の Shelby Blackstock と共有する「楽しい」クリスマスの伝統を明らかにしました:「私たちはたくさん笑います」

Reba McEntire が息子の Shelby Blackstock と共有しているクリスマスの伝統について学びましょう。

メーガン・マークルは、自然な髪のスタイリングをめぐってマライア・キャリーと結ばれました

メーガン・マークルは、自然な髪のスタイリングをめぐってマライア・キャリーと結ばれました

メーガン・マークルとマライア・キャリーが自然な髪の上でどのように結合したかについて、メーガンの「アーキタイプ」ポッドキャストのエピソードで学びましょう.

ハリー王子は家族との関係を修復できるという「希望を持っている」:「彼は父親と兄弟を愛している」

ハリー王子は家族との関係を修復できるという「希望を持っている」:「彼は父親と兄弟を愛している」

ハリー王子が家族、特にチャールズ王とウィリアム王子との関係について望んでいると主張したある情報源を発見してください。

ワイノナ・ジャッドは、パニックに陥った休暇の瞬間に、彼女がジャッド家の家長であることを認識しました

ワイノナ・ジャッドは、パニックに陥った休暇の瞬間に、彼女がジャッド家の家長であることを認識しました

ワイノナ・ジャッドが、母親のナオミ・ジャッドが亡くなってから初めての感謝祭のお祝いを主催しているときに、彼女が今では家長であることをどのように認識したかを学びましょう.

セントヘレナのジェイコブのはしごを登るのは、気弱な人向けではありません

セントヘレナのジェイコブのはしごを登るのは、気弱な人向けではありません

セント ヘレナ島のジェイコブズ ラダーは 699 段の真っ直ぐ上る階段で、頂上に到達すると証明書が発行されるほどの難易度です。

The Secrets of Airline Travel Quiz

The Secrets of Airline Travel Quiz

Air travel is far more than getting from point A to point B safely. How much do you know about the million little details that go into flying on airplanes?

Where in the World Are You? Take our GeoGuesser Quiz

Where in the World Are You? Take our GeoGuesser Quiz

The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!

バイオニック読書はあなたをより速く読むことができますか?

バイオニック読書はあなたをより速く読むことができますか?

BionicReadingアプリの人気が爆発的に高まっています。しかし、それは本当にあなたを速読術にすることができますか?

米国が選挙に影響を与えるロシアのハックに関するインテリジェンスレポートを発表

米国が選挙に影響を与えるロシアのハックに関するインテリジェンスレポートを発表

写真:ゲッティイメージズ。「最近の米国の選挙に関するロシアの活動と意図の評価」に関するFBI、CIA、およびNSAからの機密解除された文書は、「ロシアのウラジーミル・プーチン大統領が米国大統領選挙に影響を与えるキャンペーンを命じた」と主張している。

La。Manは45年間で収集された500,000ペニーで現金化

La。Manは45年間で収集された500,000ペニーで現金化

ペニーは、2006年7月6日、イリノイ州グレンビューのグレンビューコイン&コレクティブルズに展示されています。合計5,000ドル以上で、News-Starは報告します。

SaartjieBaartmanと黒人女性の身体の所有権について

SaartjieBaartmanと黒人女性の身体の所有権について

19世紀のフランスの版画サラ・バートマンのラベル・ホッテントットウィキメディア・コモンズ黒人女性の体の所有権の認識は、最も醜い歴史の断片に深く織り込まれている問題です。この有毒な考えは、地球の一部に隔離されていません。

マライア・キャリーが大晦日のパフォーマンスでソーシャルメディアのメルトダウンに対応:「ShitHappens」

マライア・キャリーが大晦日のパフォーマンスでソーシャルメディアのメルトダウンに対応:「ShitHappens」

写真:APマライアキャリーは、土曜日の夜にタイムズスクエアでディッククラークスの新年のロッキンイブウィズライアンシークレスト(このショーのタイトルはサウンドチェックを取得できますか?)のパフォーマンス中に、かなり深刻なオーディオの誤動作に苦しんでいました。最悪の問題は、キャリーの「エモーション」のパフォーマンス中に発生しました。トラックがキャリーのボーカルを断続的にしか再生せず、リップシンクをオフにしました。

米国のフィギュア スケートは、チーム イベントでの最終決定の欠如に「苛立ち」、公正な裁定を求める

米国のフィギュア スケートは、チーム イベントでの最終決定の欠如に「苛立ち」、公正な裁定を求める

ロシアのフィギュアスケーター、カミラ・バリエバが関与したドーピング事件が整理されているため、チームは2022年北京冬季オリンピックで獲得したメダルを待っています。

Amazonの買い物客は、わずか10ドルのシルクの枕カバーのおかげで、「甘やかされた赤ちゃんのように」眠れると言っています

Amazonの買い物客は、わずか10ドルのシルクの枕カバーのおかげで、「甘やかされた赤ちゃんのように」眠れると言っています

何千人ものAmazonの買い物客がMulberry Silk Pillowcaseを推奨しており、現在販売中. シルクの枕カバーにはいくつかの色があり、髪を柔らかく肌を透明に保ちます。Amazonで最大46%オフになっている間にシルクの枕カバーを購入してください

パデュー大学の教授が覚醒剤を扱った疑いで逮捕され、女性に性的好意を抱かせる

パデュー大学の教授が覚醒剤を扱った疑いで逮捕され、女性に性的好意を抱かせる

ラファイエット警察署は、「不審な男性が女性に近づいた」という複数の苦情を受けて、12 月にパデュー大学の教授の捜査を開始しました。

コンセプト ドリフト: AI にとって世界の変化は速すぎる

コンセプト ドリフト: AI にとって世界の変化は速すぎる

私たちの周りの世界と同じように、言語は常に変化しています。以前の時代では、言語の変化は数年または数十年にわたって発生していましたが、現在では数日または数時間で変化する可能性があります。

SF攻撃で91歳のアジア人女性が殴られ、コンクリートに叩きつけられた

犯罪擁護派のオークランドが暴力犯罪者のロミオ・ロレンゾ・パーハムを釈放

SF攻撃で91歳のアジア人女性が殴られ、コンクリートに叩きつけられた

認知症を患っている 91 歳のアジア人女性が最近、47 番街のアウター サンセット地区でロメオ ロレンゾ パーハムに襲われました。伝えられるところによると、被害者はサンフランシスコの通りを歩いていたところ、容疑者に近づき、攻撃を受け、暴行を受けました。

ℝ

“And a river went out of Eden to water the garden, and from thence it was parted and became into four heads” Genesis 2:10. ? The heart is located in the middle of the thoracic cavity, pointing eastward.

メリック・ガーランドはアメリカに失敗しましたか?

バイデン大統領の任期の半分以上です。メリック・ガーランドは何を待っていますか?

メリック・ガーランドはアメリカに失敗しましたか?

人々にチャンスを与えることは、人生で少し遅すぎると私は信じています。寛大に。

Language