2017-01-14 8 views
1

私のLinux IA-32プロセッサ用アセンブリプログラムには2つのストレージがあります。アセンブリのXORステートメントで3バイトのストレージのサイズを指定するにはどうすればよいですか?

inbuf: resb 3 
outbuf: resb 4 

inbuf本当に唯一の3つのバイトを必要とし、私は、任意のメモリを無駄に好きではありません。さて、私はこのようなゼロでそれらを上書きしたいとしましょう:

xor [inbuf], inbuf 
xor [outbuf], outbuf 

NASMは、私が理解しやすい操作サイズを、指定する必要があると述べています。私が代わりに

xor dword [outbuf], outbuf 

を書くことができますので、今outbufのために、これは、問題ありませんが、どうやら、3バイトとして、任意のサイズには大きキーワードはありません。 inbufのサイズはどのように指定できますか?

私は本当にゼロでストレージを上書きするための解決策を捜しているわけではないと私はそこに同じようにうまく動作し、他のものがありますが、これも

mov eax, inbuf 

のようなものを使用する方法を私の問題を解決するだろうと思います「サイズが指定されていません」というエラーは表示されません。

+3

実際には3バイトの操作サイズはありません。例えば、2 + 1バイトから合成する必要があります。たとえあったとしても、あなたのコードはあなたが望むことをすることはできません。アドレスではなく、値ではなく(直接行うことはできません)。効率を上げるために2つのパワーに固執するだけです。 PS: 'mov eax、inbuf'は、' eax'のサイズがわかっていて、暗黙的に操作サイズを決定するので、 "size not specified"エラーをトリガーしません。 – Jester

+0

@ Jester 2の累乗を使用すると少し不満です。 2バイトと1バイトを加算するとどういう意味ですか? 'xor byte + word [inbuf]、inbuf'のようなことができますか?これは構文上間違っていますか? –

+3

つまり、2つの命令を使用します。また、私が言ったように、 'xor mem、mem'をゼロに使うことはできません(2つのメモリオペランドを取らない)。 'mov単語[inbuf]、0; movバイト[inbuf + 2]、0'が動作します。 – Jester

答えて

5

私はコメント欄に道化師の正解の上に追加されます。

メモリを「xor-ing」する(ゼロにするのは意味がありませんが、他の値には価値があります)場合は、「xor 3B [inbuf]、3B [inbuf]」を実行できます

mov eax,[inbuf] ; loads value from inbuf + 1B undef 
xor [inbuf],ax ; word 
shr eax,16  ; al = b16..b23 of value @inbuf 
xor [inbuf+2],al ; byte 

4BのDWORDバリアント:

mov eax,[outbuf] 
xor [outbuf],eax 

そして、それのすべてがこれをゼロにするために、ゼロのために恐ろしいですが良いです:

mov word [inbuf],0 
mov byte [inbuf+2],0 
mov dword [outbuf],0 
このようなx86のアセンブリで

あるいは最終的に、あなたが登録32bの一部ではすでにゼロがある場合:

xor eax,eax 
mov [inbuf],ax 
mov [inbuf+2],al 
mov [outbuf],eax 

をあなたは32Bモードでは、唯一の2のべき乗の大きさのために、とだけそれらのいくつかのためにメモリにアクセスすることができます:1、2、 4汎用整数演算を使用します。

そして8またはFPUを持つ10。ああ、10は2の力ではない、私は知っている、それはいくつかのFPの事のための特別なものだ。

そしてさえ128/256/512ビット(16,32および64バイト)にアクセスすることができ、さまざまなSIMD命令は、そこにいます。

次に非算術特別な指示は時々一般的に私のように、でも例外として、それらをカウントしないだろう...など、いくつかははるかにジャンプして(私もよく分からない)、多分5または6のように、追加の余分なサイズを使用することができます全体のx86命令のデコードでは可変バイト量のアプローチを使用していますが、そのデモサイズは1Bなので、その部分の2の累乗ではありません。可能な限り

とにかく、ほとんど誰もがそれは「正しくない」hexedサイズと利用者に応じ不幸の多くをもたらすのです、唯一の議会で3つのバイトで動作しない、あなたはそれを避ける必要があります。

RGBデータで構成されるビデオRAMでも32ビット/ピクセルで整列され、パディングのように「何もない」ために4バイトごとに無駄になります(VRAMの25%が無駄になり、戻ってきましたRAMがであり、高価なであった)。

(初期のSVGA VESAモードはメモリ効率の良い24ビットモードを持っていましたが、ピクセルあたりのアドレス指定が* 3なので、コードやHWアクセラレータで使用するのは非常に面倒でした...最近では、ビデオRAM使用量のほとんどは4バイトがアルファまたはピクセルシェーダのための他の追加情報を格納することができるテクスチャ、のためのものであるので、これ以上の無駄なメモリだが、まだサイズが32ビット)


そして、どのように図3(b)をロードすることですメモリからの値:

一般的な3Bロードの場合、常に動作する必要があります。

movzx eax,byte [inbuf+2] 
shl eax,16 
mov ax,[inbuf] 

そして、あなたは、図3(b)の値が制限されたメモリページに続くメモリページ(その値は、いずれか4でアライメントされたアドレスにある、または他の法的なメモリページがそれの後にいつもあります)の最後ではないことを知っている:

mov eax,[inbuf]  ; loads desired 3B + 1B garbage 
and eax,0x00FFFFFF ; truncate it to 3B only 

(これは、次のメモリページが制限されている場合、 "inbuf"が4093番地であり、4096番のアドレスがこのプロセスに制限されているとメモリオーバーフローがクラッシュすることがありますが、通常はそうではありませんここでは "inbuf"が定義されているので、この短い変種は通常、正しい解決策として表示されます。実際にはの場合はクラッシュ)。

+0

+1は、六角サイズの問題を引き起こします。 'mov word [inbuf]、0 movバイト[inbuf + 2]、0'は良い解決策のようです。 –

+0

@JoeCocker: 'rep stos [b/w/d]'によって任意の連続メモリブロックをゼロにすることができます。例えば、 "outblock"で312Bをクリアすることができます: 'mov edi、outblock | xor eax、eax | mov ecx、312/4 | rep stosd' ..アドレスが整列していてサイズが重要でない場合、これは最速の方法かもしれません。 3または64のような固定サイズの場合、いくつかの 'movバイト/ワード/ワード[aligned_address]、0は短いサイズに最適です.64Bほど長くSIMDバリアントがあるかもしれません。より大きいカウントの場合、通常、 'rep stosd'はSIMD最適化されたソリューションと同等です。内部的に最適なuopsサブルーチンに再コンパイルされるからです。 – Ped7g

+3

BTWはアドレス整列の繰り返しテーマを認識し、2の累乗で割り切れるサイズ(少なくとも4以上)を認識します。これは、合理的であれば、データが4/8/16バイトの境界になり、そのようなサイズを持つため、大きなパフォーマンスの影響があります。たとえば、3B inbufはほとんどすべての時間に4B inbuf、3Bサイズは本当に(3Bをファイルに格納する、またはそれをいくつかのペリフェラルに送信するなどの)問題が使用されます。さもなければ、可能であれば4バイト目のゴミが一緒に使用され、4Bサイズまで "パッド"されます。 – Ped7g

関連する問題