ブール式をアセンブリコードに変換する方法

アーメドベン

私はアセンブリにまったく慣れていません。
次の関数を検討してください。
ここに画像の説明を入力してください

ここで、「+」は「Or」論理ゲートを表し、変数の連結は「And」論理ゲートを表します。
このような関数をemu8086に実装するにはどうすればよいですか?たとえば、入力パラメータがレジスタALのビットを表す場合、出力はその値を0または1に変更します。

更新:これが私がしたことです、私はそれが悪い書き方であることを知っています、そして何か提案があればそれはうまくいくようです、またはもっと簡単な方法は私
にあなたの助け、特にピーターに感謝します。

org 100h

mov al, 0A3h     pour le test              

mov ah, al
and ah, 01h        ;ah = x0 
shr al, 1

mov bl, al 
and bl, 01h        ;bl = x1 
shr al, 1

mov bh, al
and bh, 01h            
not bh
and bh, 01h         ;bh = !x2
shr al, 1

mov cl, al 
and cl, 01h        
not cl
and cl, 01h        ;cl = !x3
shr al, 1

mov ch, al
and ch, 01h        
not ch
and ch, 01h        ;ch = !x4
shr al, 1

mov dl, al
and dl, 01h        ;x5 = dl
shr al, 1

mov dh, al
and dh, 01h        
not dh
and dh, 01h        ;dh = !x6    

shr al, 1          ;al = x7  


and bh, dl
and bh, cl
and bh, ah         ;!x2 and x5 and !x3 and x0     

and dh, bl 
and dh, ch
and dh, al         ;!x6 and x1 and !x4 and x7 

or dh, bh   

mov ah, dh         ;resultat dans ah







ret
ピーター・コーデス

あなたは必ず4つので表現することをx_nお互いに次の値をビットごとれ、4ビットの値にそれらを連結していないことになっていますか?そして、バイナリ追加?代わりにそれを推測したかもしれないので。その場合、シフトとレジスタのペア間でビットを分割する方法については、https://codegolf.stackexchange.com/a/203610参照してくださいrcl reg, 1または、BMI2を搭載した最新のx86では、2xpext使用addしてそれを行うことができます

式の各グループのビットが、昇順または降順だけでなく特定の順序であるという事実、バイトを2つの4ビット整数にアンパックして通常の処理+実行するための手がかりとなる可能性があります


あなたのasmが正しい関数の例であると仮定すると

この回答の残りの部分は、2つのグループのANDとORを組み合わせて単一のブール値にし、ALで0または1生成するasmの操作を最適化することについてです。

各ビットを個別に抽出するだけの、単純で単純な実装に加えることができるいくつかの改善があります。例えば、あなたがして、前の必要はありませんし、あなたの後はありません。最初のANDは上位ビットをすべて0のままにし、次にNOTを1にし、2番目のANDを再びゼロにします。

mov bh, al
; and bh, 01h            ; This is pointless
not bh
and bh, 01h         ;bh = !x2

これをさらに進めることができます。純粋にビット演算を使用しており、各レジ​​スタの下位ビットのみを考慮しています。最後に一度、必要なビットを分離して、すべての一時的なビットでゴミを持ち歩くことができand al, 1ます。


すべてではなく一部のビットを反転するには、定数マスクでXORを使用します。たとえば、ALのビット6、4、3、2を反転し、他のビットを変更しないままにするには、xor al, 01011100b1を使用します次に、NOT命令を必要とせずに、シフトして別のレジスタに移動できます。

脚注1:末尾bは基数2 /バイナリを示します。これは、emu8086がサポートしている場合、または同等の16進数を記述する必要がある場合は、MASM構文IDKで機能します。

また、最初に抽出する代わりに、これらのレジスタにANDで直接入力できるため、必要なスクラッチレジスタは2つだけです。

   xor   al, 01011100b    ; complement bits 6,4,3,2
   mov   cl, al           ; x0, first bit of the 2&5&3&0 group

   shr   al, 1
   mov   dl, al           ; x1, first bit of the 6&1&4&7 group

   shr   al, 1
   and   cl, al           ; AND X2 into the first group, X2 & x0

   shr   al, 1
   and   cl, al           ; cl = X2 & X3 & x0

   ...                    ; cl = 2&5&3&0,  dl = 6&1&4 with a few more steps

   shr   al, 1            ; AL = x7 
   and   al, dl           ; AL = x6 & x1 & x4 & x7  (reading 6,1,4 from dl)

   or    al, cl           ; logical + apparently is regular (not exclusive) OR
   and   al, 1            ; clear high garbage
   ret

(プレーンASCIIコメントでは、最初に1つの命令ですべてを処理するため、「補完」部分は無視しました。)


これは、レジスタの最下部にビットを取得し、個別のasm命令を使用して各ブール演算(補数以外)を実行する単純な実装を使用していることを私が理解できる限りです。

より良い結果を得るには、1つの命令と並行して実行できるレジスタの8(または16)ビットを利用する必要があります。パターンが不規則であるため、ビットを簡単にシャッフルして整列させることはできません。

IDKは、AXを左シフトしてALからAHの下部にビットを取得し、ALの上部でビットをグループ化することができる賢い方法がある場合に使用します。うーん、ALの下部にビットを送り返すことshl ax交互に行うかもしれませんrol alしかし、それでもビットを分離するには7シフトが必要です。shl ax,2そしてrol al,2、一緒に行く連続ビット(7,6と3,2)は186でのみ利用可能であり、CLにカウントを入れることはほとんど価値がありません)。

迎え角の可能性が高いのはFLAGSです。ほとんどのALU操作は結果に応じてFLAGSを更新し、結果のすべてのビットが0の場合はZFを1に設定し、それ以外の場合は1に設定します。これにより、1つのレジスタのビット間で水平OR演算が実行されます。 。以来!(a | b)= !a & !b、我々は、水平および代わりのORとしてその使用への入力における非補完ビットを反転させることができます。(私は!シングルビット反転に使用しています。Cでは、ビット単位のNOT!とは異なり、ゼロ以外の数値を0に変換する~論理否定です。)

しかし残念ながら、8086にはレジスタでZFを0/1に直接変換する簡単な方法がありません。(386はsetcc r/m8、たとえばsetz dl、ZFに従ってDL = 0または1を設定します。)これCF可能です。を使用すると、レジスタがゼロ以外であることに応じてCFを設定できますsub reg, 1。これは、regが0の場合にCFを設定します(ボローが最上位になるため)。それ以外の場合はCFをクリアします。CFに従ってregで0 / -1を取得できますsbb al, al(借用で減算)。al-al部分はキャンセルされ、0 - CF。が残ります。

FLAGSを使用するように設定するには、ANDマスクを使用してビットを2つのグループに分けます。

;; UNTESTED, I might have some logic inverted.

   xor   al, 10100011b         ; all bits are the inverse of their state in the original expression.

   mov   dl, al
   and   dl, 11010010b         ; ~x[7,6,4,1]
   and   al, 00101101b         ; ~x[5,3,2,0]

   cmp   dl, 1                 ; set CF if that group was all zero (i.e. if the original AND was 1), else clear
   sbb   dl, dl                ; dl = -1 or 0 for the first group

   cmp   al, 1
   sbb   al, al                ; al = -1 or 0 for the second group.  Fun fact: undocumented SALC does this

   or    al, dl                ; The + in the original expression
   and   al, 1                 ; keep only the low bit

   ret

and al, dlDLのSBBの結果によると、ALのビットをクリアするかどうかなど、おそらくさらに多くのことができますあるいは、DLからのCF結果を使用して、ALからCFを設定する方法に影響を与えるadc al, -1代わりにcmp al, 1

を引く代わりに1sub dl, 11010010b使用したANDマスクを使用して、0すべてが設定されているかどうかを確認できます。そうでない場合は、ラップしてCFを設定します。それが役立つかどうかはわかりません。

否定/反転の量は頭の中ですぐにやっかいになりますが、コードサイズのすべてのバイトまたはパフォーマンスのすべてのサイクルが重要な場合は、それを調べる必要があります。(最近はめったにありません。SSE2またはAVXを使用してベクトル化することが多いため、フラグはありません。ベクトル要素内でビット単位で比較し、一致をすべて1と非一致に変換します。 0に。)

mov / ANDで分割した後は、ALもDLもオールワンにすること1はできないため、加算がゼロにラップされることはありません。ではsbb al, -1、0または1を追加して、ZFを設定できるでしょうか。

分岐する場合は、jzまたはでZFで分岐しても問題ありませんjnzこれは8086でも最適かもしれません。たとえば、最初のANDグループがを与える場合1、他のグループを分離する必要はありません。だから、xor al, ...それに応じてビットを補完するために、その後、test al, mask1/ jnz check_other_group/mov al,1高速パスを通じて良い秋でしょう。

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

アセンブリで3番地コードを変換する

分類Dev

IA32アセンブリをCコードに変換する

分類Dev

アセンブリ言語をPythonコードに変換する

分類Dev

CコードをアセンブリMips言語に変換する

分類Dev

シェルコードを読み取り可能なアセンブリコード/命令に変換する方法は?

分類Dev

アセンブラプログラムをシェルコードに正しく変換する方法は?

分類Dev

シェルコードをアセンブリ命令に逆アセンブルする方法は?

分類Dev

このアセンブリコードをCコードに変換しようとしています

分類Dev

jsonエントリをテーブルレコードに変換する最良の方法

分類Dev

整数をドローアブルに変換する方法

分類Dev

アセンブリ コードを整理する方法

分類Dev

再コンパイルせずに衛星アセンブリを変換する方法は?

分類Dev

x86アセンブリジャンプテーブルをCに変換する

分類Dev

dotnetcoreにアセンブリを動的にロードする方法

分類Dev

C ++コード(BASICインタープリター)をARMアセンブリにコンパイルする

分類Dev

Pythonコードをアセンブリに翻訳する

分類Dev

cコードをアセンブリの16進表現にどのように変換しますか?

分類Dev

8086アセンブラはどのようにラベルをオペコードに変換しますか?

分類Dev

GCCインラインアセンブリCMOVをVisualStudioアセンブラーに変換する

分類Dev

次の機械語コード(0x2237FFF1)をMIPSアセンブリに変換します

分類Dev

アセンブリでユーザー入力を取得して大文字に変換する方法

分類Dev

LC3 のアセンブリ コードでソート アルゴリズムを作成する方法

分類Dev

パンダを使用してブール式にアクセスする方法

分類Dev

パンダを使用してブール式にアクセスする方法

分類Dev

機械語を読み取り可能なアセンブリに変換する方法(IDAフリー)

分類Dev

このコードをノンブロッキングでロックフリーに変換する方法は?

分類Dev

g ++アセンブリコード命令アドレスを取得する方法

分類Dev

既存のアセンブリコードとの競合を回避するためにCコードを作成/ビルドする方法は?

分類Dev

アセンブリコードをcコードにリバースエンジニアリングする

Related 関連記事

  1. 1

    アセンブリで3番地コードを変換する

  2. 2

    IA32アセンブリをCコードに変換する

  3. 3

    アセンブリ言語をPythonコードに変換する

  4. 4

    CコードをアセンブリMips言語に変換する

  5. 5

    シェルコードを読み取り可能なアセンブリコード/命令に変換する方法は?

  6. 6

    アセンブラプログラムをシェルコードに正しく変換する方法は?

  7. 7

    シェルコードをアセンブリ命令に逆アセンブルする方法は?

  8. 8

    このアセンブリコードをCコードに変換しようとしています

  9. 9

    jsonエントリをテーブルレコードに変換する最良の方法

  10. 10

    整数をドローアブルに変換する方法

  11. 11

    アセンブリ コードを整理する方法

  12. 12

    再コンパイルせずに衛星アセンブリを変換する方法は?

  13. 13

    x86アセンブリジャンプテーブルをCに変換する

  14. 14

    dotnetcoreにアセンブリを動的にロードする方法

  15. 15

    C ++コード(BASICインタープリター)をARMアセンブリにコンパイルする

  16. 16

    Pythonコードをアセンブリに翻訳する

  17. 17

    cコードをアセンブリの16進表現にどのように変換しますか?

  18. 18

    8086アセンブラはどのようにラベルをオペコードに変換しますか?

  19. 19

    GCCインラインアセンブリCMOVをVisualStudioアセンブラーに変換する

  20. 20

    次の機械語コード(0x2237FFF1)をMIPSアセンブリに変換します

  21. 21

    アセンブリでユーザー入力を取得して大文字に変換する方法

  22. 22

    LC3 のアセンブリ コードでソート アルゴリズムを作成する方法

  23. 23

    パンダを使用してブール式にアクセスする方法

  24. 24

    パンダを使用してブール式にアクセスする方法

  25. 25

    機械語を読み取り可能なアセンブリに変換する方法(IDAフリー)

  26. 26

    このコードをノンブロッキングでロックフリーに変換する方法は?

  27. 27

    g ++アセンブリコード命令アドレスを取得する方法

  28. 28

    既存のアセンブリコードとの競合を回避するためにCコードを作成/ビルドする方法は?

  29. 29

    アセンブリコードをcコードにリバースエンジニアリングする

ホットタグ

アーカイブ