アセンブラ初心者スレッド 2©2ch.net

レス数が900を超えています。1000を超えると表示できなくなるよ。
2017/04/13(木) 17:35:55.70ID:1WMn3pSz
初心者OK!質問大歓迎!のアセンブラのスレッドです。
基本情報の勉強中の人、PICやH8を勉強中の学生などなど…

前スレ
アセンブラ初心者スレッド
http://echo.2ch.net/test/read.cgi/tech/1314502612/

関連スレ
アセンブラ 13
http://echo.2ch.net/test/read.cgi/tech/1314512680/
2020/08/04(火) 15:22:33.51ID:CK7AS0VE
>>836
そういうことではなく、レジスタをアドレス空間にマッピングしているCPUは、
例えば、アドレス空間の 0〜255 番地の部分をレジスタ専用に
して、CPUの外部のアドレスバスには信号が出ないようにしていることが多い。
そして、
mov [0],値
と書くと、r0 に「値」を書き込むようにCPUが設計されていて、
外部のDRAMなどには全く信号が送られないようになっている。
2020/08/04(火) 15:30:51.43ID:z2HwYjyf
>>837
そういうのもあるだろうけど、それは最初からそういう設計にしているからそう動くということだよね。
アドレス空間にある入出力領域は固定的である必要はないので、バスに出た信号をどう処理するかは
設計者が自由に決められるはず。なので、バスに出た信号をメモリだけに送ることもできるし、
CPUとメモリ両方に送ることもできる。用途に合わせればいいということかと。
2020/08/04(火) 15:34:19.50ID:CK7AS0VE
>>838
「レジスタをアドレス空間にマッピングしているCPU」
というのは、最初から設計されているCPUのことだと思うぞ。
実際、ポケコンのCPUもそんな感じだった。
2020/08/04(火) 16:20:06.60ID:z2HwYjyf
>>839
設計者が最初からそう設計したのならそうだろうね。
固定的である必要がないというのは、設計するとき設計者がどちらでも選べるという意味だよ。
2020/08/04(火) 19:31:24.43ID:aUyBUHRY
>>837
ああ、ずっと何の話をしてるのか分からなかったけど0ページの話ね。
2020/08/16(日) 16:21:04.44ID:Cqk7CoxF
>>839 アルディーノのCPUがそれだ。レジスタがメモリにマッピングされている。
2020/08/17(月) 08:09:56.01ID:tzd42ouk
LLVMが吐き出したx86-64アセンブラコードを入力とするツールを作りたいのですが
このアセンブラコードの文法に関する資料って何処にあるんでしょうか
ttps://llvm.org/docs/Extensions.html
ttps://sourceware.org/binutils/docs/as/
あたりにも各命令をどのように記述するかまでは載っていないように見えるのですが・・・
2020/08/17(月) 10:11:33.24ID:RiKJFl8Z
命令セットレベルの話ならインテルのマニュアルでも見ろとしか。
2020/08/17(月) 11:34:25.89ID:NVTg5S9X
>>843
Intelに大量の PDF マニュアルがあり、詳細に書いてある。
2020/08/17(月) 11:37:24.90ID:NVTg5S9X
>>843
LLVMツールの出力する、native の x86 や x64 のアセンブリコードは、
試してみる限り、masm 形式ではない。
見た目はgccの形式に似ている。
LLVMのarm版が出力したnativeアセンブリコードは、gccのgasが解釈して正しくobjファイル
までアセンブルできたことがある。
x86 や x64 の場合は、そこまでは試していない。
847843
垢版 |
2020/08/17(月) 12:59:34.65ID:WGW93JMF
ぶっちゃけパーサーをどう作るかって所なのですが

>>844-845
そうなのですが
1.CPUのマニュアルの命令表記とアセンブラの命令表記は例外なく一致するのか
 基本的にはマニュアル通りで良さそうですが表記に揺れがあった場合困る
2.リファレンスはAMDかIntelか
 この命令セットを設計したのはAMDだし処理系の対応もAMD64が先行していたはず
あたりはイマイチはっきりしないです

>>846
吐かれるアセンブラコードはGASベースで独自のディレクティブが追加されているように見えますね
2020/08/18(火) 01:12:29.19ID:xqTakpBf
>>847
命令表記は、8バイトのオペランド(や型)を表すのにdqwordとowordで表す
2つの流儀がある。
さらに、mmwordを使う流儀もあるが、浮動小数点演算のx87の文化では
浮動小数点でも専用の型名は無くて、dwordでfloat、qwordでdoubleを扱う
流儀があった。
そこにxmmやmmxのためだけにmmwordを持ってきた意図やセンスは
賛否が分かれるところだと思う。
2020/08/18(火) 01:28:37.97ID:xqTakpBf
>>847
x64のリファレンスは、原則的にAMDで、AMDにも詳しいマニュアルがある。
命令表記は、絶対アドレス addr に対する間接参照で、昔は、[addr]と
表記していたものが、x64だと、マシン語レベルでは絶対アドレスを埋め込まずに、
ripからの相対アドレスrel_addrを用いて、[rip+rel_addr]のような意味になっている
があるが、アセンブラレベルでそれを表記する時、どうするかと言う問題がある。

masmだと昔から、
mov eax,MyWork1
・・・
ret
MyWork dd 1234
と書いてきた。普通のアセンブラなら、
mov eax,[MyWork1]
・・・
ret
MyWork: dd 1234
と書くところを。
しかし、rip相対になった場合、
mov eax,[rip+MyWork]
と書くと意味に合わないし、かと言って、
mov eax,[rip+rel MyWork]
と書くのも長くなる。意味的には、Masmだと
mov eax,MyWork
なのだが、マシン語レベルでは、絶対アドレス/相対アドレスのどちらで表現されるか、
明確に表すことはできなくなるジレンマがある。
2020/08/21(金) 15:25:03.93ID:EskYTmRE
destにメモリを指定できる命令ってパイプラインをストールさせやすいように思うけどそんな事はないの?
x64だと
ADD r/m64,r64
みたいなの
2020/08/21(金) 20:30:50.01ID:+dwilF/E
確かにストールしやすいとは言えるが影響度合いはプロセッサ次第で、そういう命令を持ったプロセッサはちゃんと考慮した設計がされている。

例えばOut of Order実行を行うプロセッサはパイプラインに結果書込み待ちをするキューを持ったステージがあって、メモリ書き込み前に後続の命令を実行可能だから単純にストールはしない。

前後の命令に依存があればストールするのはレジスタ相手でも同じことだし、命令でロードとモディファイとストアを分けても実行する内容は同じなのだから、結局はプロセッサアーキテクチャ毎に最適化が必要なことには変わりがない。
2020/08/22(土) 00:25:14.47ID:Rco6UMRM
インテル(R) 64 アーキテクチャーおよび IA-32 アーキテクチャー最適化リファレンス・マニュアル
を良く呼んだら書いてあったわ
> 一般的に、各命令を構成するマイクロオペレーション(μOP)の数を考慮し、単一マイク
> ロオペレーション(μOP)の命令、4 マイクロオペレーション(μOP)未満の単純な命令、
> マイクロシーケンサー ROM が必要な命令の順で優先して、命令を選択すると良い。
> 〜
> ・複数のマイクロオペレーション(μOP)からなる一連の命令を分割できない場合は、
>  同等の異なる命令シーケンスに分割する。例えば、読み出し−変更−書き込み命令は、
>  読み出し−変更命令 + ストア命令に分割すると、高速化が可能である。この手法を利
>  用すれば、新しいコードシーケンスが元のコードシーケンスより大きくなった場合で
>  も、パフォーマンスが向上する。
らしいのでADD m64,r64みたいな命令はパフォーマンス上のデメリットがあるから使用を控えた方が良さそう
2020/08/29(土) 02:13:33.36ID:kcJTulzj
x64命令の動作を確認するのに対話式にアセンブル&実行&レジスタの確認が出来るツールとかないかな?
各値を変えながら試行錯誤したいけどソース書いてアセンブルしてデバッガに読み込んでステップ実行してだと手間すぎる

今MULのフラグの更新動作がAMDの資料を見てもIntelの資料を見てもググってももよく判らない
2020/08/29(土) 17:42:02.36ID:CDQjtNyx
>>853
フラグ類は、言葉で説明が難しいので、擬似コードで説明されている Intel の資料が
どこかにあるはず。
2020/08/29(土) 18:05:14.09ID:CDQjtNyx
>>853
Intel® 64 and IA-32 Architectures
Software Developer’s Manual
Volume 2A:
Instruction Set Reference, A-M

-------------------------------------------------
[MUL—Unsigned Multiply]
・・・
Flags Affected
The OF and CF flags are set to 0 if the upper half of the result is 0; otherwise, they
are set to 1. The SF, ZF, AF, and PF flags are undefined.
2020/08/29(土) 18:39:05.44ID:kcJTulzj
>>855
その文章は確認していてAMD64のドキュメントにも
>If the upper half of the product is non-zero, the instruction sets the carry flag (CF) and overflow flag
>(OF) both to 1. Otherwise, it clears CF and OF to 0.
と似たような記述があるんだけど双方の資料に書いてある"upper half"がどの部分を示しているのか判らない
演算結果の上半分が入るDレジスタの事?
2020/08/29(土) 19:05:00.05ID:CGaweZC2
>>856
Intelの日本語マニュアルには処理の疑似コードが載ってる。
これによると、上半分というのは、各命令で使うレジスタサイズの上半分とわかる。
8,16,32bitそれぞれ場合によって上半分の長さが変わるのでそう書くしかない。
だから64bitの場合の上半分は上位32bitになる。

操作
IF (NumberOfOperands = 1)
 THEN IF (OperandSize = 8)
  THEN
   AX ← AL ? SRC (* signed multiplication *)
   IF AL = AX
    THEN CF ← 0; OF ← 0;
    ELSE CF ← 1; OF ← 1;
   FI;
  ELSE IF OperandSize = 16
   THEN
    DX:AX ← AX ? SRC (* signed multiplication *)
    IF sign_extend_to_32 (AX) = DX:AX
     THEN CF ← 0; OF ← 0;
     ELSE CF ← 1; OF ← 1;
    FI;
   ELSE (* OperandSize = 32 *)
    EDX:EAX ← EAX ? SRC (* signed multiplication *)
    IF EAX = EDX:EAX
     THEN CF ← 0; OF ← 0;
     ELSE CF ← 1; OF ← 1;
  FI;
FI;
2020/08/29(土) 19:47:52.94ID:cC8g9MrB
upper half of the product だから乗算結果の上半分だ。
疑問の余地は無いと思うがな…
2020/08/29(土) 20:22:30.40ID:GYyhmMZY
CPU emulator Unicorn
https://www.unicorn-engine.org/
860デフォルトの名無しさん
垢版 |
2020/08/30(日) 01:05:43.21ID:BjChy3oe
IF sign_extend_to_32 (AX) = DX:AX
 THEN CF ← 0; OF ← 0;
 ELSE CF ← 1; OF ← 1;
FI;

これだと符号拡張したものと比較しているから、言葉による説明と違っている。
基本的に、mulは、符号無しの整数に対する掛け算なのだが。
2020/08/30(日) 01:11:49.03ID:BjChy3oe
>>857
それは、mul(符号無し掛け算)ではなく、imul(符号付掛け算)の擬似コードで、
英語版でも、同じような擬似コードが書いてあり、言葉による説明は、
次のようになっている:
Flags Affected
For the one operand form of the instruction, the CF and OF flags are set when signif-
icant bits are carried into the upper half of the result and cleared when the result fits
exactly in the lower half of the result. For the two- and three-operand forms of the
instruction, the CF and OF flags are set when the result must be truncated to fit in the
destination operand size and cleared when the result fits exactly in the destination
operand size. The SF, ZF, AF, and PF flags are undefined.
2020/08/30(日) 01:22:29.16ID:BjChy3oe
ちなみに、同じビット数の2つの整数の掛け算は、結果の内、掛ける前の整数の
ビット数の部分に限定した部分だけを見れば、符号付き掛け算と符号無し掛け算
で結果が変わらない。
一方、imulは、2オペランド以上のものは、結果のビット数が、掛ける前と同じ。
そして、mulは、2オペランド以上のものが用意されて無い。
これは、最初に述べた性質から、imulとmulで、2オペランド以上の場合では、
結果が変わらなくなってしまうため、imulだけで、符号無し掛け算にも対応できる
ためである。
863デフォルトの名無しさん
垢版 |
2020/08/30(日) 14:10:51.87ID:GgAZZaQa
https://www.youtube.com/watch?v=1EqyId5U8zA
https://www.youtube.com/watch?v=HOx7R3rgaTs
https://www.youtube.com/watch?v=M3x5J4jUYrc
https://www.youtube.com/watch?v=4ly0dPogeXY
https://www.youtube.com/watch?v=7EbNp1pDRPk
2020/08/30(日) 14:26:36.90ID:EVylyaDc
>>863
昔は大学教授しかこういう講義してなかったが、今は若い女の子が講義してくれるのかw
いい時代になったな
2020/08/30(日) 18:38:46.61ID:Oy/VxFsh
おっぱいしか目に入らん
2020/08/31(月) 15:24:59.40ID:r6h0vUdb
セクションとかも理解してくれるx64逆アセンブラとかないのかな
セクション情報やデバッグ情報をディレクティブ等でコードと一緒に出力してくれるとうれしい
2020/09/01(火) 10:42:01.73ID:vwihzMdy
>>864
昔は子供向けのベーマガに載ってるレベル。
2020/09/01(火) 17:43:15.76ID:8L3AfpS1
>>866
Linux?
869デフォルトの名無しさん
垢版 |
2020/09/03(木) 12:52:56.48ID:ZDuIxl5I
良い時代になった
https://www.youtube.com/watch?v=nUG_ymIss_s
https://www.youtube.com/watch?v=wEVe6XOojCM
https://www.youtube.com/watch?v=Ox2z9MYpRCg
2020/09/03(木) 14:20:08.59ID:cueCbpYZ
>>869
秋月に女の子が部品買いに来てるのなんて見たことないんだが、時代はそこまで来てるのか?
女の子がハンダごて握ってなんか作ってる姿は萌えるかも知れない
2020/09/04(金) 10:09:14.61ID:KmpQA39o
>>870
今時ネット通販だろうけど本屋と同じで
たまたま近くに置いてあるのに目が止まるのが良かったりするんだけどな
パートおばさんのハンダ付け作業なんて若年化する前にほぼ中国海外にいったろう
最近は新入社員研修に後ろから二人羽織状態で手を握りながら・・
2020/09/06(日) 06:21:38.35ID:EKeL4GkH
ドキュメント72時間で秋葉原の部品屋やってたけど
女子高生がオリジナルのペンライトを作るために来てた
2020/09/06(日) 09:40:26.46ID:TNZ7/NP8
良スレ
2020/09/07(月) 16:54:29.21ID:0bCSYOR0
欧米では女性も半田くらいできるけどな

https://makezine.jp/wp-content/uploads/2016/03/stock-photo-beautiful-woman-repair-soldering-a-printed-circuit-board-204001492.jpg
2020/09/07(月) 17:52:16.84ID:0w2E3x4d
>>874
撮影用のモデルだろ、半田が付いているのは裏面だ
2020/09/07(月) 18:30:23.60ID:3pB/Wjpj
それ以前に火傷する
2020/09/07(月) 18:41:49.64ID:hcXGR9uA
>>874
そんなとこ持ったら火傷で大変なことになってるw
撮影のとき誰も注意しなかったのかよ
2020/09/07(月) 22:17:45.58ID:KQEAaFWf
半田ごてを持つ部分が間違ってるし、基盤もハンダ付けする面は上下逆だし、
さあに、こういう基盤は、最近ではかなりの部分がロボットでハンダ付けしてると
聞いている。
2020/09/07(月) 22:44:57.51ID:0w2E3x4d
https://makezine.jp/blog/2016/03/beautiful-woman-soldering-stock-photo-wrong.html
880デフォルトの名無しさん
垢版 |
2020/09/08(火) 03:25:35.85ID:jacy6RM2
何周遅れか判らんくらい激しく概出過ぎてつまらん
2020/09/09(水) 19:36:30.15ID:HmJqfQ+A
>>875
そっちにもつっこみ所あったんか…今頃知った
2020/09/13(日) 00:55:43.99ID:NuGQj3YA
論理演算より、鼻筋の整形が気になって・・・
2020/09/25(金) 21:12:03.86ID:1nrszLVg
鼻の穴にもつっこむ所あったんか…
2020/11/02(月) 22:13:42.36ID:KqjMEGzA
775にしてはアルミ電解バリバリだな
2020/11/19(木) 16:32:15.09ID:7GrsSxFi
アセンブラからドライバを読みたいですが、どうやってしますか?
2020/11/19(木) 20:17:00.91ID:4w1/CW5J
日本語が変
887デフォルトの名無しさん
垢版 |
2020/11/25(水) 09:47:14.54ID:gT5in2ls
好奇心でMS-DOS 6.2にJWasmを入れてアセンブラ入門サイトを見ながら学習しています。
大きな値を10進変換したい場合はどうすれば良いのでしょう?
DX:AX ÷ 10dがしたい。

INT21hファンクションコールでAH=36hを実行してAX * BX * CXした結果を
DIV 10するのに、商が16ビットを超えるので例外が発生する。

入門中なので、2バイトまでの環境しか使い方がわかりません。

4バイトのレジスタが使えれば解決する話なのかも知れませんけど、、
DX:AXから計算する方法ないか調べています。
結局、EDX:EAXを10dで割る事になっても同じことが起きるので
2020/11/25(水) 12:44:21.97ID:jzvQX9aE
>>887
(1)まず、DXを10で割る。
その時の商をQ1(ax),余りをR1(dx)とする。
(2)
mov ax,元のAX
xor dx,dx  ;← dx=0
add ax,R1
adc dx,0
とする。これは、元のAXにR1を足したものを(dx:ax)に入れていることに相当する。
(3)
(dx:ax)を10で割り、商をQ2(ax)、余りをR2(dx)とする。
(4) 最終的な商Qは、(Q1:Q2), 余りRは、R2である。
2020/11/25(水) 12:46:48.67ID:jzvQX9aE
>>888
すまん。ちょっと間違った。(2)は正しくは、
(2)
mov ax,元のAX
とする。
これは、これは、(dx:ax)=(R1:元のAX)に相当する。

だった。
2020/11/25(水) 12:50:41.35ID:jzvQX9aE
コードに直すとこうなると思う。

;入力: (dx:ax)
;出力: (Q1:ax)=商, 余り=dx

mov original_ax,ax
mov ax,dx
xor dx,dx
mov cx,10
div cx
mov Q1,ax
mov ax,original_ax
div cx
;商=(Q1:ax), 余り=dx
ret
2020/11/25(水) 13:07:31.94ID:jzvQX9aE
>>887
32BIT(4バイト)命令を使っていいなら、(dx:ax)/10 は、
shl edx,16
mov dx,ax
mov eax,edx
xor edx,edx
mov ecx,10
idiv ecx
で、eax に32BITの商、edx に余り(0〜9)が出る。
2020/11/25(水) 13:12:20.82ID:jzvQX9aE
>>891
idivじゃなくて、divが正しい。
2020/11/25(水) 14:53:28.45ID:h9isg/D4
定数の除算に糞遅いDIV命令を使うとか
2020/11/25(水) 14:55:43.27ID:gT5in2ls
MUL BX
MUL CX
MOV Q2, DX
MOV Q1, AX
MOV BX, 10
DIV_LOOP:
XOR DX, DX
MOV AX, Q2
DIV BX
MOV Q2, AX
MOV AX, Q1
DIV BX
MOV Q1, AX
ADD DX, '0'
PUSH DX
OR AX, AX
JNZ DIV_LOOP

こんな感じですか?
気になったのですが、MOV DX, 0ではなくて、XOR DX, DXなのは処理が速いから?
CMP AX, 0よりも、OR AX, AXの方が良いのでしょうか?
2020/11/25(水) 15:47:06.05ID:T5VOSp5s
速いから
ではないでしょ
2020/11/25(水) 16:46:45.83ID:jzvQX9aE
>>894
>気になったのですが、MOV DX, 0ではなくて、XOR DX, DXなのは処理が速いから?
>CMP AX, 0よりも、OR AX, AXの方が良いのでしょうか?
昔は速かったので今でも伝統的に0を代入する変わりにxor reg,regを
使い、cmp ax,0の変わりに or ax,axを使う人が多い。
しかし、その「昔」とは、80486とかよりもずっと昔の初代8086の時代のことかもしれない。
ただし、xor reg,regだとフラグ類まで初期化されてしまうので、mov reg,0を使った方が
良い場合がある。

>>895
今は速くは無いが、昔は速かった。
その伝統が何故か今でも継承されている。
2020/11/25(水) 16:58:10.99ID:jzvQX9aE
>>894
冒頭の
MUL BX
MUL CX
の部分が怪しい。一行目で結果がDX:AXに入っているのに、二行目ではそれを
無視しているが、無視してはいけない。

また、最後の
OR AX, AX
JNZ DIV_LOOP
の判定は間違い。
これだと、Q2がまだ非0の場合にもループが終わってしまう。
ちゃんと、Q2が非0の場合もループを続行しなくてはならない。

また、Qは、商(quotient)の頭文字を使っただけで、伝統的には、
意味が余り分からない変数は、work1 などを使う慣例があったりする。
意味が分かる場合には、意味が分かるような変数名にする。
2020/11/25(水) 17:02:18.40ID:jzvQX9aE
なお、Q1は、説明の都合上、数学と似た感覚で短い変数を付けたが、
アセンブラなどに書く場合には、もっと長い名前にした方がいい。
短いとアセンブラが何かと混同して問題になるかも知れないから。
例えば、レジスタ名にr1などというものがある場合があるので注意。
2020/11/25(水) 17:44:43.84ID:h9isg/D4
>>896
伝統だけじゃない
メリットがある
2020/11/26(木) 00:21:00.79ID:5BVCYzUa
皆知ってるてのになw
2020/11/26(木) 01:11:06.89ID:lH6B10sG
>>899
では、現在のIntelCPUにおいて、
・mov reg,0の代わりにxor reg,reg
・cmp eax,0の変わりにor eax,eax
を使うメリットをそれぞれ書いてみてください。
2020/11/26(木) 12:23:04.16ID:kAbnbrOP
# mk_src.rb
def mk_src( md, loop1 = 1000000, loop2 = 1000 )
tit, fpath, asm_str = case md
when 1; [ 'imd', 'imd.c', %Q{\t\tasm( "movl $0, %eax\\ncmpl $0, %eax" );\n} ]
when 2; [ 'reg', 'reg.c', %Q{\t\tasm( "xorl %eax, %eax\\norl %eax, %eax" );\n} ]
end
File.open( fpath, 'w:UTF-8' ){|fh|
fh.print <<_EOT_
#include <stdlib.h>
#include <stdio.h>
#include <windows.h>

int main(void)
{
LARGE_INTEGER qpff, qpf0, qpf1;
QueryPerformanceFrequency( &qpff );

unsigned int n = #{loop2};
QueryPerformanceCounter( &qpf0 );
while( n-- ){
#{asm_str * loop1}
}
QueryPerformanceCounter( &qpf1 );
printf( " #{tit}. time %lf[ms]\\n", (double)(qpf1.QuadPart - qpf0.QuadPart) * 1000.0 / qpff.QuadPart );
return 0;
}
_EOT_
} # File.open
end

mk_src( 1 )
mk_src( 2 )
2020/11/26(木) 12:23:28.07ID:kAbnbrOP
$ uname -srvmo
MINGW64_NT-10.0-18363 3.1.7-340.x86_64 2020-09-22 20:54 UTC x86_64 Msys

$ gcc imd.c -O0 -o imd; gcc reg.c -O0 -o reg
8291652 imd.exe
6291780 reg.exe

$ ./imd.exe; ./imd.exe; ./imd.exe; ./imd.exe
imd. time 221.844800[ms]
imd. time 236.904100[ms]
imd. time 205.867200[ms]
imd. time 242.199800[ms]

$ ./reg.exe; ./reg.exe; ./reg.exe; ./reg.exe
reg. time 134.806000[ms]
reg. time 145.542900[ms]
reg. time 147.039100[ms]
reg. time 143.031100[ms]
2020/11/26(木) 12:58:51.67ID:lH6B10sG
Intelの最適化マニュアルを見たが、or,xor,cmp,movのlatencyやthroughputは
CPUによりマチマチで、絶対にどれが速いと言うようなことはいえないと思う。
ややこしいのは、movは、latencyが1や0.5, throughoutが0.5なのに対し、
xorは、latencyが1, throughtputが0.33や0.5となっていたりする。
これもCPUIDによってさまざま。
表の中のCPUIDの表記法も独特なので、どれが最新のCPUに対応しているのかも
個人的には今のところ分からない。
2020/11/26(木) 13:10:05.83ID:Ndl69lfH
>>904
常に最新の情報を見て一番いいものを使うのが正しいよね。
伝統とか言ってるようじゃダメ。頭が腐る。
2020/11/26(木) 14:55:11.18ID:l8W6EZba
馬鹿ほど脳みそ足りないからAppleのようにすぐ互換性を捨てたがる。
そんな馬鹿は伝統を重んじてきたx86系を使わないでほしい。
2020/11/26(木) 16:30:36.87ID:s+oX3EtE
>>896
不具合なければどっちでもよくね?
どっちかにしなければいけないほど古いPCを今でも使っている人?
2020/11/26(木) 18:31:44.20ID:b0/J9kY8
命令自体のクロック数は多少違うかもしれんがキャッシュ効率も考えれば1バイト命令のxor ax,axの方が正解の確率が高いと思うよ。
2020/11/26(木) 18:39:31.62ID:rqBz/pid
てかxor reg, regはIntelやAMDの最適化マニュアルにも書いてあるくらいなんだが
2020/11/26(木) 18:48:11.36ID:HK02mgb4
x86は386,486,586,686と拡張されてきて、その度に命令が拡張されてきてる。これらはどれもx86だが、
これらの互換性を取ろうとすると386に合わせるしかなくなる。しかしそれでは今のWindowsは動かない。
一般の人にとって互換性というのは普段使っているアプリケーションが動けばいいので、それでほぼ支障ない。

最近のIntel CPUはHaswell、Broadwell、Skylake、Kebylakeと来ているが、これらの間だけ見ても
命令が拡張されているので完全な互換性はない。ならば互換性を重視して、最新CPUの便利な機能を使うな
ということになると技術者のレベルは昔のまま上がらないことになる。それは時代に取り残されることにならないか。

386はシングルコアだったが今はマルチコアが当たり前の時代だ。しかしソフトウェアは今でもシングルコアを
前提に書くことが多い。その方が簡単だしそれでも動くからだ。しかし、搭載されているコア数を最初に見て、
マルチコアだったら並列処理できるところは並列で動かせば早くなるのがわかっていても。互換性のために
わざとそうしないとしたらそれはただの怠慢に過ぎないだろう。そういう人はx86系を使わないでほしい。
2020/11/26(木) 18:55:48.10ID:l8W6EZba
このように互換性捨てろという奴は頭悪いとよく分かる。
PowerPC、IA64、MIPSから何も学んでないのだ。
2020/11/26(木) 19:02:03.76ID:rqBz/pid
x86を捨てたがっているのはIntel自身なんだよなぁ
2020/11/26(木) 19:40:42.10ID:lH6B10sG
>>908
x86のXOR reg,reg, MOV reg,0 はどちらも2バイト命令でコード長は同じ。
Z80とは違う。
2020/11/26(木) 19:52:22.98ID:lH6B10sG
>>909
今見てみたら、xor reg,reg や sub reg,reg には「実行依存性」を断ち切る効果が
あると書いてあった。Pentium 4 から特別な扱いをする様になったとか。
つまり、xor reg,regだとフラグまで初期化してしまうので、フラグが決まるまで
Latencyを待つ必要が無い。
ところが、mov reg,0だとフラグは引き継ぐから前の命令によってフラグが
決まるまで次の命令の実行が待たされることがあるのかな。
もしかしたら、CPU内部では、ZF,CF,SFなどと独立して変更できずに、
EFLAGS全体を1つのレジスタの様に扱うことが基本になっていて、
一部だけを変更しようとすると待機が発生しやすくなるのかもしれない。
2020/11/26(木) 19:56:51.64ID:lH6B10sG
>>914
スマン。
そういう意味ではないようだわ。
or eax,ebx
とかだと、直前までの命令でeaxとebxの両方のレジスタの値が決まってないと
パイプライン上でこの命令ALUのステージを実行することは出来ないので待機が
発生する。
ところが、xor eax,eax だと直前までの命令のeaxの結果がどうであれ、この
命令は必ずeaxを0にしてしまうから、待機する必要が無い、という意味だった。
2020/11/26(木) 20:18:29.14ID:l8W6EZba
コード長はくだらん揚げ足取りに見える。普通にオペランドも入れて解釈すべきでキャッシュ効率は不利。
昔からレジスタ初期化で多用されるxorは組み合わせ回路、ワイヤードロジック一発で多くのCPUでも特別扱い。

XOR r32, r32 L: 0.07ns= 0.2c T: 0.07ns= 0.24c
OR r32, r32 L: 0.29ns= 1.0c T: 0.07ns= 0.25c
AND r32, r32 L: 0.29ns= 1.0c T: 0.10ns= 0.33c
2020/11/26(木) 20:42:01.46ID:l8W6EZba
よく使う命令を重点的にトランジスタを大量投入して速くしようというのはコードの互換性を大事にしてるからの発想。古いコードでも速く動かしてやるという努力の賜物のx86。
一方、使わない命令は削除、もう頭使うのが嫌だからと最適化はコンパイラの仕事と最適化を放り出して衰退したRISC哲学。
2020/11/26(木) 20:43:40.28ID:lH6B10sG
>>916
mov reg,0
は、オペランドも全て含めて2バイト。
0は、short formで8BITオペランドになるから。
xor reg,regは、immオペランドが無くても2バイト。
なぜなら、movは、特別な短いマシン語が割り当てられているのに、xorは
そうではないから。
919デフォルトの名無しさん
垢版 |
2020/11/26(木) 20:50:33.32ID:weG7Hi1V
タブ機能付きのソフト(AcrobatReaderとかテキストエディターとか)の現在アクティブな
タブのファイルパスのアドレスを調べたいんですけど、めちゃめちゃ頑張ったんですけど無理でした。
わかったことは、AcrobatReaderの場合、開いた順にインデックスが振られて(初めの値は0
ではなく1)、アクティブタブのインデックスが格納されたアドレスがあるということです。
もしくはインデックスが振られるのではなく、ファイルパスを開いた順に配列にプッシュして
ファイルパス配列[アクティブタブのインデックス - 1] のタブをアクティブにしろという命令が出てる。
前者の場合、インデックスが格納されてるアドレスがどこかさっぱりわかんなくって、ファイルパス
のアドレスからちょっと前をみたりマックスパスの260Byte後ろのとこを見たりしたんですけど
それらしきインデックスが見つかりませぬ。
それで、ファイルパスにアクセスしてる関数を見たんですけどアセンブリ言語サッパリ( 一一)
どなたか助言お願いします。

ファイルパスにアクセスしてるらしき関数↓
AcroRd32.dll+4637E - 33 D2 - xor edx,edx
AcroRd32.dll+46380 - 8B C1 - mov eax,ecx
AcroRd32.dll+46382 - 66 39 11 - cmp [ecx],dx
AcroRd32.dll+46385 - 74 08 - je AcroRd32.dll+4638F
AcroRd32.dll+46387 - 83 C0 02 - add eax,02 { 2 }
AcroRd32.dll+4638A - 66 39 10 - cmp [eax],dx
AcroRd32.dll+4638D - 75 F8 - jne AcroRd32.dll+46387
AcroRd32.dll+4638F - 2B C1 - sub eax,ecx
AcroRd32.dll+46391 - D1 F8 - sar eax,1
AcroRd32.dll+46393 - 5D - pop ebp
AcroRd32.dll+46394 - C3 - ret

もう1週間くらい頑張ってます。宜しくお願いします。
2020/11/27(金) 00:50:22.02ID:dazyxaWu
>>918
ならないな。バイナリ出して。

0100 mov ax,0
0103 xor ax,ax
0100 B8 00 00 31 C0

B8 00 00 00 00 mov eax,0
33 C0 xor eax,eax
2020/11/27(金) 00:56:36.27ID:lOUpIwv2
OllyDbg などの逆アセンブラツールを使えないのか?
2020/11/27(金) 14:37:53.57ID:35rurNSb
>>919
何をしたいのかが分からないが、例えばVS2019にAcrobatReaderの*.exeファイルを
ドラッグアンドドロップして、デバッグを開始し、タブにファイルを開いた状態にする。
そこでデバッガによりアプリを停止させて、メモリー内でそのファイル名を検索する。
どうやって検索すればよいかは良く知らない。
VS2019ではなく、OllyDbgなどを使えばよいかもしれない。
それでファイル名が入っているメモリーアドレスは分かることは分かる。
もう一つは、ファイルをオープンする場合、必ず Win32 の CreateFile APIが呼び出される
ので、CreateFileの 関数アドレスにブレイクポイントを仕掛ける。
その状態で実行すると何回かブレイクしているうち、タブのファイル名に対して
CreateFileが呼び出されることがあるはず。
その状態になったら、コールスタック(呼び出し履歴)を辿って、CreateFileを
呼び出している場所を見つける。そうすると、ファイル名を渡しているコードが
見つかる。
2020/11/27(金) 14:42:33.59ID:35rurNSb
>>922
なお、ファイルパスの入っているアドレスは分かる様になるが、
当然、アドレスは毎回変化するので、果たして何をしたいか、ということになる。
ファイルパスを入れているメモリーブロックを malloc や new している
コードを探すことは出来るかもしれないし、そのアドレスをどこかに格納している
コードも探すことは可能かも知れない。
が、複雑すぎて、そこで得た知見で何かをするということは
アセンブラに最高に詳しい人でもかなり難しい。
2020/11/27(金) 14:47:20.40ID:35rurNSb
>>923
例えば、OllyDbgなどを使えば、ファイルパスが入っているメモリーアドレスを
検索して探し出すことは出来るかも知れない。
それで見つかったアドレスを X とする。
今度は、そのアドレス X を格納しているメモリーを探すこともできることはできる
可能性がある。
その場合、little endian なので、バイトレベルでは下位バイトから上位バイトに
向かって格納されていることに注意する。
ただし、アドレスXが格納されているアドレスは、複数見つかる可能性がある。
また、X そのものではなく、X より少し小さいアドレスが格納されていることもありえる。
だから、このような解析は難しいものとなる。

またこのような方法以外に、dumpbin に /disasm オプションをつけて Acrobat の *.exeを
逆アセンブルした結果を併用するのが基本。
2020/11/27(金) 14:53:31.46ID:35rurNSb
>>924
そのような方法で粘り強く解析していくと、dumpbinの逆アセンブルコードの
どのあたりで、ファイルパスを格納するメモリーを確保し、そのアドレスを
どこかに記録しているコードは見つかる可能性は有る。
ただし、問題はそう簡単ではなく、「どこかに記録している」の「どこか」
がまた、毎回アドレスが変わることにある。
C/C++で言えば、非常に多数の構造体が連鎖的にリンクされているから。
このくらいの規模のアプリだと、その連鎖は、10以上になることは少なくない。
連鎖の仕方もif分などで場合分けされていて、条件によって複雑に代わりうる。
ソースコードがあっても複雑すぎてなにをやっているかを理解することはとても
困難。だから、ソースコードが無い状態でそれを理解することはとてつもなく
難しい。
2020/11/27(金) 19:42:52.50ID:ljdbT47c
でも有能なハッカーはそれを解読するよね
2020/11/27(金) 22:46:27.98ID:ULLAjR/s
>>926
お前さんは有能なハッカーですか?
2020/11/28(土) 00:05:40.76ID:OUdaBd4w
>>926
ハッカーは、ハッキングに関係ないことは何もやらないでしょう
2020/11/28(土) 00:34:33.70ID:qjEapHwo
> mov reg,0
> は、オペランドも全て含めて2バイト。
> 0は、short formで8BITオペランドになるから。

これって本当なの? そうアセンブルされないけど。
2020/11/28(土) 17:46:27.32ID:WIRcuTWz
>>929
どのCPUかによって変わるだろ。
自分が使ってるCPUのマニュアルを読んで自分で確認したらどうか。
2020/11/28(土) 20:17:09.98ID:qjEapHwo
アスペなの? ボクのCPUの話じゃなく、
本人はz80ではなくx86だと言ってるからx86の話を聞いているんだよ。
他社の互換含めてx86系CPUが一体どれだけあると思ってるの? 全部確認できるわけないじゃん。
932デフォルトの名無しさん
垢版 |
2020/11/28(土) 20:21:31.70ID:kjtXSxRe
>>919
です!!>>922 さんありがとうございました!
なんとアクティブタブのファイルパスアドレス見つかりました!
AHKですけど、よかったら皆さんこの関数使ってください!

;==================================================
JEE_GetAcroRd32Path(hWnd)
{
WinGetClass, vWinClass, % "ahk_id " hWnd
if !(vWinClass = "AcrobatSDIWindow")
return
WinGet, vPID, PID, % "ahk_id " hWnd
WinGet, vPPath, ProcessPath, % "ahk_id " hWnd
FileGetVersion, vPVersion, % vPPath

MAX_PATH := 260
;PROCESS_QUERY_INFORMATION := 0x400 ;PROCESS_VM_READ := 0x10
if !hProc := DllCall("kernel32\OpenProcess", UInt,0x410, Int,0, UInt,vPID, Ptr)
return
if !vAddress && A_Is64bitOS
{
DllCall("kernel32\IsWow64Process", Ptr,hProc, IntP,vIsWow64Process)
vPIs64 := !vIsWow64Process
}
2020/11/28(土) 20:22:46.29ID:Sl4N7Gov
AMD64やIA-32eのマニュアルに2バイトで0クリア出来るオペコードはないように見えるな
934デフォルトの名無しさん
垢版 |
2020/11/28(土) 20:23:26.87ID:kjtXSxRe
if !vAddress
{
VarSetCapacity(MEMORY_BASIC_INFORMATION, A_PtrSize=8?48:28, 0)
vAddress := 0
Loop
{
if !DllCall("kernel32\VirtualQueryEx", Ptr,hProc, Ptr,vAddress, Ptr,&MEMORY_BASIC_INFORMATION, UPtr,A_PtrSize=8?48:28, UPtr)
break

vMbiBaseAddress := NumGet(MEMORY_BASIC_INFORMATION, 0, "Ptr")
vMbiRegionSize := NumGet(MEMORY_BASIC_INFORMATION, A_PtrSize=8?24:12, "UPtr")
vMbiState := NumGet(MEMORY_BASIC_INFORMATION, A_PtrSize=8?32:16, "UInt")
;vMbiProtect := NumGet(MEMORY_BASIC_INFORMATION, A_PtrSize=8?36:20, "UInt")
vMbiType := NumGet(MEMORY_BASIC_INFORMATION, A_PtrSize=8?40:24, "UInt")

vName := ""
if (vMbiState & 0x1000) ;MEM_COMMIT := 0x1000
&& (vMbiType & 0x1000000) ;MEM_IMAGE := 0x1000000
;&& (vMbiProtect = 0x4) ;PAGE_READWRITE := 0x4
{
vPath := ""
VarSetCapacity(vPath, MAX_PATH*2)
DllCall("psapi\GetMappedFileName", Ptr,hProc, Ptr,vMbiBaseAddress, Str,vPath, UInt,MAX_PATH*2, UInt)
if !(vPath = "")
SplitPath, vPath, vName

}
935デフォルトの名無しさん
垢版 |
2020/11/28(土) 20:25:32.47ID:kjtXSxRe
if InStr(vName, "AcroRd32.dll")
{
;get address where path starts
;if vPIs64{
; vAddress := vMbiBaseAddress + 0x19d3d9c
;}
;else{
vAddress := vMbiBaseAddress + 0x19d3d9c
;}
break
}
vAddress += vMbiRegionSize
if 0
if (vAddress > 2**32-1) ;4 gigabytes
{
DllCall("kernel32\CloseHandle", Ptr,hProc)
return
}
}
}
936デフォルトの名無しさん
垢版 |
2020/11/28(土) 20:26:33.51ID:kjtXSxRe
VarSetCapacity(MEMORY_BASIC_INFORMATION, A_PtrSize=8?48:28, 0)
if vAddress
&& DllCall("kernel32\VirtualQueryEx", Ptr,hProc, Ptr,vMbiBaseAddress, Ptr,&MEMORY_BASIC_INFORMATION, UPtr,A_PtrSize=8?48:28, UPtr)
{
memVal := ReadMemory32(vAddress, 0, vPID)
memVal := ReadMemory32(memVal, 0x78, vPID)
memVal := ReadMemory32(memVal, 0x18, vPID)
memVal := ReadMemory32(memVal, 0x10, vPID)
memVal := ReadMemory32(memVal, 0x10, vPID)
;memVal += 0x0
vPath := ""
VarSetCapacity(vPath, MAX_PATH*2)
DllCall("psapi\GetMappedFileName", Ptr,hProc, Ptr,vMbiBaseAddress, Str,vPath, UInt,MAX_PATH*2, UInt)
if InStr(vPath, "AcroRd32.dll")
{
vPath2 := ""
VarSetCapacity(vPath2, MAX_PATH*2, 0)
DllCall("ReadProcessMemory", "UInt", hProc, UInt, memVal, Str, vPath2, Uint, MAX_PATH*2, UPtr,0)
vPath3 := StrGet(&vPath2, "cp932")
}
}
DllCall("kernel32\CloseHandle", Ptr, hProc)
return vPath3
}
レス数が900を超えています。1000を超えると表示できなくなるよ。