初心者OK!質問大歓迎!のアセンブラのスレッドです。
基本情報の勉強中の人、PICやH8を勉強中の学生などなど…
前スレ
アセンブラ初心者スレッド
http://echo.2ch.net/test/read.cgi/tech/1314502612/
関連スレ
アセンブラ 13
http://echo.2ch.net/test/read.cgi/tech/1314512680/
アセンブラ初心者スレッド 2©2ch.net
■ このスレッドは過去ログ倉庫に格納されています
2017/04/13(木) 17:35:55.70ID:1WMn3pSz
446デフォルトの名無しさん
2019/10/29(火) 17:54:53.05ID:VnX4qZP9 >>445
当時、ほとんどのアプリは基本ロジック部分はC/C++言語で書いていて、
グラフィックなどの速度が必要な部分をアセンブラで書くということをやっていた。
だから確かにアセンブラからは32BITアドレッシングは可能であっても、
C/C++が使えなければ現実的に使うことは無理であった。
だから、何らかのC/C++コンパイラが必要となった。それが結構高価であった
ことと、既にWin95に一般民が移行していたので選択の余地は狭かった。
ただし、移行というより、1995はパソコン元年などといわれたくらい、
初めてパソコンを使い始める大挙して押し寄せた。
だから、DOSエクステンダは魅力的ではあっても、その流れに逆らうことは
難しかった。
当時、ほとんどのアプリは基本ロジック部分はC/C++言語で書いていて、
グラフィックなどの速度が必要な部分をアセンブラで書くということをやっていた。
だから確かにアセンブラからは32BITアドレッシングは可能であっても、
C/C++が使えなければ現実的に使うことは無理であった。
だから、何らかのC/C++コンパイラが必要となった。それが結構高価であった
ことと、既にWin95に一般民が移行していたので選択の余地は狭かった。
ただし、移行というより、1995はパソコン元年などといわれたくらい、
初めてパソコンを使い始める大挙して押し寄せた。
だから、DOSエクステンダは魅力的ではあっても、その流れに逆らうことは
難しかった。
447デフォルトの名無しさん
2019/10/29(火) 18:03:50.25ID:I2MyCbhZ 俺の質問めっちゃ低レベル…
LDやSTなどの命令やオペランドは主記憶に記憶されることは分かったんですが、
コメントも同様に、オペランドとかの後に記憶されているんですか?
LDやSTなどの命令やオペランドは主記憶に記憶されることは分かったんですが、
コメントも同様に、オペランドとかの後に記憶されているんですか?
448デフォルトの名無しさん
2019/10/29(火) 18:11:29.42ID:n7hbVS5F >>447
一般的な処理系ならコメントはアセンブル時に削除される
一般的な処理系ならコメントはアセンブル時に削除される
449デフォルトの名無しさん
2019/10/29(火) 18:48:08.61ID:ex5BLs+R 今でもはじめて読む8086読んどけかと思えば絶版なのかな...amazon在庫無いね
>>441
>プロテクトモードにした場合、DOSは、仮想8086モードで動かさないといけなかった。
いいえ、リアルモードで DOS を起動して、ユーザープログラムが勝手にプロテクトモードに変更してなんら問題ないですよ
プロテクトモードから一時的にリアルモードに戻ることはできませんが、プロテクトモードで割り込みテーブルを再設定すれば問題ないですね
>自力でDOSをプロテクトモードにするのはほとんど不可能で、DPMIやVCPIという既存のプログラムが利用された。
まあそれは事実ですが、あと DOS エクステンダーがよく使われましたね
>プロテクトモードにした場合、DOSは、仮想8086モードで動かさないといけなかった。
いいえ、リアルモードで DOS を起動して、ユーザープログラムが勝手にプロテクトモードに変更してなんら問題ないですよ
プロテクトモードから一時的にリアルモードに戻ることはできませんが、プロテクトモードで割り込みテーブルを再設定すれば問題ないですね
>自力でDOSをプロテクトモードにするのはほとんど不可能で、DPMIやVCPIという既存のプログラムが利用された。
まあそれは事実ですが、あと DOS エクステンダーがよく使われましたね
>>442
>既に、EMSメモリを使うために、プロテクトモードは使われてしまっており、
>DOSは仮想8086モードで動いていた。そのせいで、自作プログラムで勝手に
>プロテクトモードをコントロールすることは不可能だった。
EMS なんて非常に使いにくいものはさっさと追放しちゃえばよかったのですよ
>既に、EMSメモリを使うために、プロテクトモードは使われてしまっており、
>DOSは仮想8086モードで動いていた。そのせいで、自作プログラムで勝手に
>プロテクトモードをコントロールすることは不可能だった。
EMS なんて非常に使いにくいものはさっさと追放しちゃえばよかったのですよ
453デフォルトの名無しさん
2019/10/29(火) 19:36:42.19ID:QynZyw6q まず
80286ではプロテクトモードからリアルモードに戻ることが出来なかったため
戻るために特殊な仕組みが必要になり、プロテクトモードが非常に使いにくかった
386以降は、単純にリアルモードに戻ることが可能になったため使いやすくなり
セグメントのリミットを設定し直してそのまま戻ることで
リアルモード(DOS)から4G全てにアクセスすることも出来るようになった
そして、仮想86モードでの割り込み処理も、別に複雑な処理などは基本的には必要ない
なぜならBIOSにある、元の割り込み処理ルーチンに処理させれば良いだけだから
もちろんIDTをセットアップして処理するプログラムは用意する必要はあるが
大半はスタックにあるリアルモードでの戻り番地等を設定して、
あたかもリアルモードで割り込みが起こったかのようにBIOSやDOSの割り込みベクタテーブルのアドレスに飛ぶだけ
自前で処理する必要があるのは、GPフォルトやページフォルト、
それにA20の操作の処理が入ったらページテーブルを書き換える等するだけ
その程度でも、HMA64KやUMBを用意して空きメモリに余裕があるDOSを動かすくらいなら出来た
(ただし、DMAにも対処するにはまた別途処理が必要)
もちろんEMS等に対応するには、そのための処理ルーチンを用意する必要があるし
EMSやVCPI程度ならともかく、DPMIにも対応するとなると、かなり面倒くさかっただろうとは思う
80286ではプロテクトモードからリアルモードに戻ることが出来なかったため
戻るために特殊な仕組みが必要になり、プロテクトモードが非常に使いにくかった
386以降は、単純にリアルモードに戻ることが可能になったため使いやすくなり
セグメントのリミットを設定し直してそのまま戻ることで
リアルモード(DOS)から4G全てにアクセスすることも出来るようになった
そして、仮想86モードでの割り込み処理も、別に複雑な処理などは基本的には必要ない
なぜならBIOSにある、元の割り込み処理ルーチンに処理させれば良いだけだから
もちろんIDTをセットアップして処理するプログラムは用意する必要はあるが
大半はスタックにあるリアルモードでの戻り番地等を設定して、
あたかもリアルモードで割り込みが起こったかのようにBIOSやDOSの割り込みベクタテーブルのアドレスに飛ぶだけ
自前で処理する必要があるのは、GPフォルトやページフォルト、
それにA20の操作の処理が入ったらページテーブルを書き換える等するだけ
その程度でも、HMA64KやUMBを用意して空きメモリに余裕があるDOSを動かすくらいなら出来た
(ただし、DMAにも対処するにはまた別途処理が必要)
もちろんEMS等に対応するには、そのための処理ルーチンを用意する必要があるし
EMSやVCPI程度ならともかく、DPMIにも対応するとなると、かなり面倒くさかっただろうとは思う
455デフォルトの名無しさん
2019/10/29(火) 21:10:57.31ID:KWhI3UgV >>449
Amazonに「64ビットアセンブラ入門」というのがある。
Amazonに「64ビットアセンブラ入門」というのがある。
456デフォルトの名無しさん
2019/10/29(火) 21:13:34.56ID:KWhI3UgV457デフォルトの名無しさん
2019/10/29(火) 21:41:39.59ID:KWhI3UgV アセンブラでガリガリ書きたい人は、フルアセンブラで書いたOSがある。
プログラムもアセンブラで書く。サンプルプログラムもたくさんある。
DOSのように終わったOSではないので、今のPCにもインストールできる。
Kolibriは初期のMenuetからフォークした32bit OS。Menuetは64bit。
面倒なアドレッシング制限もなく、画面表示も簡単にできる。
日本語にはまだ対応していないので、誰かが日本語化すればユーザが増えるかも。
menuet os
http://www.menuetos.net/
kolibri os
http://kolibrios.org/en/index
プログラムもアセンブラで書く。サンプルプログラムもたくさんある。
DOSのように終わったOSではないので、今のPCにもインストールできる。
Kolibriは初期のMenuetからフォークした32bit OS。Menuetは64bit。
面倒なアドレッシング制限もなく、画面表示も簡単にできる。
日本語にはまだ対応していないので、誰かが日本語化すればユーザが増えるかも。
menuet os
http://www.menuetos.net/
kolibri os
http://kolibrios.org/en/index
458デフォルトの名無しさん
2019/10/29(火) 21:48:10.11ID:VnX4qZP9 >>452
そのプリフィックスは、データ用とアドレス用のものだけど、
データ用の方はどのモードからも普通に使えた。ところが、
アドレス用の方はプロテクトモードでしか使えず、
仮想8086モードでも使用不可能になっていた。
それが、Wintel同盟がDOSを使えなくしてWindowsだけを使えるように
するための策略だったのではないかと疑っている
(そんな風に設計する理由は特に無かったのに。)。
そのプリフィックスは、データ用とアドレス用のものだけど、
データ用の方はどのモードからも普通に使えた。ところが、
アドレス用の方はプロテクトモードでしか使えず、
仮想8086モードでも使用不可能になっていた。
それが、Wintel同盟がDOSを使えなくしてWindowsだけを使えるように
するための策略だったのではないかと疑っている
(そんな風に設計する理由は特に無かったのに。)。
459デフォルトの名無しさん
2019/10/29(火) 22:01:50.22ID:VnX4qZP9 >453
>そして、仮想86モードでの割り込み処理も、別に複雑な処理などは基本的には必要ない
>なぜならBIOSにある、元の割り込み処理ルーチンに処理させれば良いだけだから
>もちろんIDTをセットアップして処理するプログラムは用意する必要はあるが
>大半はスタックにあるリアルモードでの戻り番地等を設定して、
>あたかもリアルモードで割り込みが起こったかのようにBIOSやDOSの割り込みベクタテーブルのアドレスに飛ぶだけ
ここは言うほど簡単ではなかった。まず、32BITモードから仮想8086モードの
サブルーチン(割り込みハンドラも)を呼ぶ方法がcall命令としては用意されて
いなかった。だから、32BIT--->V8086モードへは、call命令から帰るリターン命令
の一種であるところのiret命令を使わなくてはいけなかった。その設定が細かい話
になるので細心の注意が必要であった。さらに、V8086--->32BITモードの
呼び出し元へ戻る際には、ret命令ではなく、コールゲートに対する特殊な
call命令か、int命令を用いなくてはならなかった。しかし、もともとのDOSの
割り込みハンドラの最後の部分にはそんな命令が書かれているわけは無いので、
工夫が必要であった。割り込みハンドラから戻ってくるアドレスに、
コールゲートに対するcall命令か、32BITモードに対するint命令かを
「仕掛けて」おく必要があった。どっちにしろ、それはもともと戻るための
命令ではないものを戻る命令として用いているので、スタックなどをきちんと
戻すためには細心の注意が必要だった。
さらに、二重に割り込みが入ったような場合に対応させるためにも、
非常に注意深くスタックの構造を設計しておく必要があった。それは、
32BITモードと16BITモードスタックのの二重構造だった。というのは、
80386のスタックは、32BITモードと16BITモードで全く別の領域を
使う仕組みになっていたので、連続的にすることはできなかったためである。
>そして、仮想86モードでの割り込み処理も、別に複雑な処理などは基本的には必要ない
>なぜならBIOSにある、元の割り込み処理ルーチンに処理させれば良いだけだから
>もちろんIDTをセットアップして処理するプログラムは用意する必要はあるが
>大半はスタックにあるリアルモードでの戻り番地等を設定して、
>あたかもリアルモードで割り込みが起こったかのようにBIOSやDOSの割り込みベクタテーブルのアドレスに飛ぶだけ
ここは言うほど簡単ではなかった。まず、32BITモードから仮想8086モードの
サブルーチン(割り込みハンドラも)を呼ぶ方法がcall命令としては用意されて
いなかった。だから、32BIT--->V8086モードへは、call命令から帰るリターン命令
の一種であるところのiret命令を使わなくてはいけなかった。その設定が細かい話
になるので細心の注意が必要であった。さらに、V8086--->32BITモードの
呼び出し元へ戻る際には、ret命令ではなく、コールゲートに対する特殊な
call命令か、int命令を用いなくてはならなかった。しかし、もともとのDOSの
割り込みハンドラの最後の部分にはそんな命令が書かれているわけは無いので、
工夫が必要であった。割り込みハンドラから戻ってくるアドレスに、
コールゲートに対するcall命令か、32BITモードに対するint命令かを
「仕掛けて」おく必要があった。どっちにしろ、それはもともと戻るための
命令ではないものを戻る命令として用いているので、スタックなどをきちんと
戻すためには細心の注意が必要だった。
さらに、二重に割り込みが入ったような場合に対応させるためにも、
非常に注意深くスタックの構造を設計しておく必要があった。それは、
32BITモードと16BITモードスタックのの二重構造だった。というのは、
80386のスタックは、32BITモードと16BITモードで全く別の領域を
使う仕組みになっていたので、連続的にすることはできなかったためである。
460デフォルトの名無しさん
2019/10/29(火) 22:02:17.16ID:VnX4qZP9 >>453
>386以降は、単純にリアルモードに戻ることが可能になったため使いやすくなり
>セグメントのリミットを設定し直してそのまま戻ることで
>リアルモード(DOS)から4G全てにアクセスすることも出来るようになった
ここも、隠れ機能としてそういうものがあると聞いたことがあるが、
多分、ちゃんと公表されていなかったのではないかと思う。
>386以降は、単純にリアルモードに戻ることが可能になったため使いやすくなり
>セグメントのリミットを設定し直してそのまま戻ることで
>リアルモード(DOS)から4G全てにアクセスすることも出来るようになった
ここも、隠れ機能としてそういうものがあると聞いたことがあるが、
多分、ちゃんと公表されていなかったのではないかと思う。
461デフォルトの名無しさん
2019/10/29(火) 22:38:00.70ID:Zl5vhLEl >>452
66、67プレフィックスは使えても64KBを超えるオフセットになると一般保護例外が発生する
もう、誰かが書いてるが一度、プロテクトモードに入ってセグメントリミットを設定しなおして
リアルモードに戻れば一般保護例外は発生しなくなるけど、
他のプロテクトモードを使うソフトを一緒に使ってる場合、不具合が発生する可能性はあった
66、67プレフィックスは使えても64KBを超えるオフセットになると一般保護例外が発生する
もう、誰かが書いてるが一度、プロテクトモードに入ってセグメントリミットを設定しなおして
リアルモードに戻れば一般保護例外は発生しなくなるけど、
他のプロテクトモードを使うソフトを一緒に使ってる場合、不具合が発生する可能性はあった
462デフォルトの名無しさん
2019/10/29(火) 22:40:47.58ID:Zl5vhLEl463デフォルトの名無しさん
2019/10/29(火) 22:46:10.13ID:VnX4qZP9464デフォルトの名無しさん
2019/10/29(火) 22:55:18.61ID:VnX4qZP9 >>463
記憶をたどれば、確か、セグメントリミットを4GBに設定したセグメントエントリ
を持ったGDTテーブルを用意してその先頭アドレスをGDTRに入れた後、
確か、CR0 の BIT をいじった後、far jmpを行うとプロテクトモードに入るが、
far jmpを行わなければ、中途半端な状態になって、4GBアクセスできる
リアルモードになるんだった気がする。だから、その後、far jmpを行うと
モードが切り替わってしまうので、その命令は、アプリが暴走しても
絶対に使っちゃいけない。ただし、リアルモードなのでアプリが暴走すると
OSもつられてこけるので、関係ないっちゃ関係ない。
記憶をたどれば、確か、セグメントリミットを4GBに設定したセグメントエントリ
を持ったGDTテーブルを用意してその先頭アドレスをGDTRに入れた後、
確か、CR0 の BIT をいじった後、far jmpを行うとプロテクトモードに入るが、
far jmpを行わなければ、中途半端な状態になって、4GBアクセスできる
リアルモードになるんだった気がする。だから、その後、far jmpを行うと
モードが切り替わってしまうので、その命令は、アプリが暴走しても
絶対に使っちゃいけない。ただし、リアルモードなのでアプリが暴走すると
OSもつられてこけるので、関係ないっちゃ関係ない。
465デフォルトの名無しさん
2019/10/29(火) 23:31:54.59ID:Zl5vhLEl >>463
386はプロテクトモードからリアルモードに戻ることができる
286は戻れないのでハードウェアでCPUだけリセットして復帰するように作る必要がある
PC/ATやその互換機、PC9801の286マシンにはそういう仕組みがハードウェアで備わってる
386はプロテクトモードからリアルモードに戻ることができる
286は戻れないのでハードウェアでCPUだけリセットして復帰するように作る必要がある
PC/ATやその互換機、PC9801の286マシンにはそういう仕組みがハードウェアで備わってる
466447
2019/10/30(水) 00:23:36.64ID:JIJxpsW5467デフォルトの名無しさん
2019/10/30(水) 02:14:08.40ID:qopAd6nC 割れ厨か
468デフォルトの名無しさん
2019/10/30(水) 06:36:17.87ID:hEWImuUH まず、リアルモードでも仮想86モードでも、
アドレスサイズプリフィックスを使うこと自体ではGPフォルトは発生しない
例えば、lea eax, eax+eax*4 という、5倍する時に使うコードは
仮想86モードでも普通に使える
何度も書いているが、
リアルモードと仮想86モードではセグメントのリミットが64Kに設定されているために
その範囲外にアクセスするとGPフォルトになるというだけなので
一旦セグメントリミットを4Gにしてからリアルモードに戻れば、例外を起こさずに全アドレスにアクセスできる
farジャンプは、パイプラインに残っている命令キューをフラッシュするためのものなので、セグメントリミットとはあまり関係ない
例えば自前で仮想86モードを利用した仮想EMSドライバを書く場合
最初にプロテクトモードに移行してリミットを変え、すぐにリアルモードに戻る
そしてリアルモードのコードで全領域をいろいろセットアップし、それから仮想86モードになってDOSに制御を移すという手法が使えた
仮想86モードでの割り込みハンドラも、仮想86モードでのスタック上にある戻り番地の部分に
割り込みベクタテーブルからの番地を置いて(テーブルにそして保存されているSPも変えて)iretするだけだから
別に難しくない
仮想86中でのiretも何か対処する必要があった気もするけど
いずれにせよGPフォルトのハンドラ内でどんな命令が例外を起こしたか調べる必要があるので、
その内部でiretだったらどうするというテーブルジャンプ対応程度で足りたはず
アドレスサイズプリフィックスを使うこと自体ではGPフォルトは発生しない
例えば、lea eax, eax+eax*4 という、5倍する時に使うコードは
仮想86モードでも普通に使える
何度も書いているが、
リアルモードと仮想86モードではセグメントのリミットが64Kに設定されているために
その範囲外にアクセスするとGPフォルトになるというだけなので
一旦セグメントリミットを4Gにしてからリアルモードに戻れば、例外を起こさずに全アドレスにアクセスできる
farジャンプは、パイプラインに残っている命令キューをフラッシュするためのものなので、セグメントリミットとはあまり関係ない
例えば自前で仮想86モードを利用した仮想EMSドライバを書く場合
最初にプロテクトモードに移行してリミットを変え、すぐにリアルモードに戻る
そしてリアルモードのコードで全領域をいろいろセットアップし、それから仮想86モードになってDOSに制御を移すという手法が使えた
仮想86モードでの割り込みハンドラも、仮想86モードでのスタック上にある戻り番地の部分に
割り込みベクタテーブルからの番地を置いて(テーブルにそして保存されているSPも変えて)iretするだけだから
別に難しくない
仮想86中でのiretも何か対処する必要があった気もするけど
いずれにせよGPフォルトのハンドラ内でどんな命令が例外を起こしたか調べる必要があるので、
その内部でiretだったらどうするというテーブルジャンプ対応程度で足りたはず
469デフォルトの名無しさん
2019/10/30(水) 06:40:30.90ID:hEWImuUH >>464
リアルモードに戻る正式な手順は、「各セグメントのリミットを64Kに設定してからレジスタ(確かcr0だと思ったが)を設定」で
それを4Gに設定したままで戻れば、64Kの制限が解除される
もちろん16bitレジスタは16bitでしかアドレスできないので、32bitレジスタを使う必要がある
リアルモードに戻る正式な手順は、「各セグメントのリミットを64Kに設定してからレジスタ(確かcr0だと思ったが)を設定」で
それを4Gに設定したままで戻れば、64Kの制限が解除される
もちろん16bitレジスタは16bitでしかアドレスできないので、32bitレジスタを使う必要がある
470デフォルトの名無しさん
2019/10/30(水) 09:06:54.09ID:C/RG5q83 >>468
>farジャンプは、パイプラインに残っている命令キューをフラッシュするためのものなので、セグメントリミットとはあまり関係ない
関係大有りです。リアルモードからプロテクトモードへのモード切替時に、
必ず far jmp命令を行うことが仕様で決まっているのです。
CR0 の PE BITを1にしただけでは切り替わりません。その後に必ずfar jmp
命令を実行するまでがモード切替の手順の一部として決まっています。
>farジャンプは、パイプラインに残っている命令キューをフラッシュするためのものなので、セグメントリミットとはあまり関係ない
関係大有りです。リアルモードからプロテクトモードへのモード切替時に、
必ず far jmp命令を行うことが仕様で決まっているのです。
CR0 の PE BITを1にしただけでは切り替わりません。その後に必ずfar jmp
命令を実行するまでがモード切替の手順の一部として決まっています。
471デフォルトの名無しさん
2019/10/30(水) 09:09:35.16ID:C/RG5q83 >>469
CR0のPEビットを1にした状態でfar jmpするとプロテクトモードに切り替わります。
CR0のPEビットを1にした状態でfar jmpするとプロテクトモードに切り替わります。
472デフォルトの名無しさん
2019/10/30(水) 15:33:25.51ID:bv6PVv2A >>457
MonaOS 知ってる人減ったな
MonaOS 知ってる人減ったな
473デフォルトの名無しさん
2019/10/30(水) 23:02:51.33ID:6OkRkWLe >>466
残念ながらチクチク解析しないといけないです。なぜならもしコメントが残っていたら、「○○製品で使ったコード」とか
社内秘の内容が書いてあるかも知れず、そんなものが外に出たら大変だからです。
ソフトウェアのバージョンとか表に出ても構わない内容ならDBで定数文字列として書いておけばバイナリーにも
残るので逆アセンブルすれば見えます。
残念ながらチクチク解析しないといけないです。なぜならもしコメントが残っていたら、「○○製品で使ったコード」とか
社内秘の内容が書いてあるかも知れず、そんなものが外に出たら大変だからです。
ソフトウェアのバージョンとか表に出ても構わない内容ならDBで定数文字列として書いておけばバイナリーにも
残るので逆アセンブルすれば見えます。
474デフォルトの名無しさん
2019/10/30(水) 23:39:08.38ID:acFyRUep ダンプリストからでも処理を追えるから問題ない
475デフォルトの名無しさん
2019/10/31(木) 11:59:20.35ID:+ME5Ro2x 我々のコリブリ
476デフォルトの名無しさん
2019/11/01(金) 06:35:57.29ID:x4OgavLA Super ASCIIでDOSエクステンダーの連載があったな
その連載の最初の頃にプロテクトモードで64KBのリミッターを解除して
リアルモードに戻るサンプルプログラムが載ってた
DOSエクステンダーの話になってからは雑誌に載るソースコードは一部分のみで
全体のソースコード自体はASCIIがやってたアスキーネットで公開してたけど
その連載の最初の頃にプロテクトモードで64KBのリミッターを解除して
リアルモードに戻るサンプルプログラムが載ってた
DOSエクステンダーの話になってからは雑誌に載るソースコードは一部分のみで
全体のソースコード自体はASCIIがやってたアスキーネットで公開してたけど
477デフォルトの名無しさん
2019/11/01(金) 08:50:52.10ID:/dldU/F5 昔書いたコードを眺めてみたが
プロテクトモードに移るだけなら far jmp は必要なく、
shortジャンプでキューをクリアするだけで動いてたな
もちろん、16bitプロテクトモードに移るだけでcsのリミットも触っておらず
リアルモードと命令の意味が変わらない(命令長が変化しない等)からこそ出来る技
32bitモードに移行したらプリフィックスの意味も即値やアドレスの長さも全て変わるから
farジャンプは絶対必要だろう
386の時代の話だから、以後のでも通用するかはわからないが
プロテクトモードに移るだけなら far jmp は必要なく、
shortジャンプでキューをクリアするだけで動いてたな
もちろん、16bitプロテクトモードに移るだけでcsのリミットも触っておらず
リアルモードと命令の意味が変わらない(命令長が変化しない等)からこそ出来る技
32bitモードに移行したらプリフィックスの意味も即値やアドレスの長さも全て変わるから
farジャンプは絶対必要だろう
386の時代の話だから、以後のでも通用するかはわからないが
478デフォルトの名無しさん
2019/11/01(金) 08:51:34.31ID:/dldU/F5 こんな感じ
Enable4G proc
call Relocation
add ds:[D_GDTR].@BASE32, eax
pushr <ds, es>
pushf
cli
lgdt D_GDTR
mov eax, cr0
;and eax, not _PG
or al, _PE
mov cr0, eax
jmp short $+2 ;flush queue
movseg <ds, es>, GD_D4G, ax
mov eax, cr0
and al, not _PE
mov cr0, eax
jmp short $+2 ;flush queue
mov al, 2
out 0F6h, al ; A20マスク解除
sti
popf
popr
ret
endp
Enable4G proc
call Relocation
add ds:[D_GDTR].@BASE32, eax
pushr <ds, es>
pushf
cli
lgdt D_GDTR
mov eax, cr0
;and eax, not _PG
or al, _PE
mov cr0, eax
jmp short $+2 ;flush queue
movseg <ds, es>, GD_D4G, ax
mov eax, cr0
and al, not _PE
mov cr0, eax
jmp short $+2 ;flush queue
mov al, 2
out 0F6h, al ; A20マスク解除
sti
popf
popr
ret
endp
479デフォルトの名無しさん
2019/11/01(金) 08:53:59.78ID:/dldU/F5 で、仮想86モードに移行する時は、far jmpが必須
なぜなら、仮想86モードに移行するためには
仮想86モード用にセットアップされたTSSを使った特殊なタスクに移行する必要があり
そのためにはプロテクトモード内でのcsの書き換え、つまり、farjmpが必要となるから
これは呼び出し部分
GotoV86 proc
pushad
pushr <fs, gs>
pushf
call ModeSwitch
popf
mov al, 3
out 0F6h, al ; force A20 OFF
popr
popad
ret
endp
なぜなら、仮想86モードに移行するためには
仮想86モード用にセットアップされたTSSを使った特殊なタスクに移行する必要があり
そのためにはプロテクトモード内でのcsの書き換え、つまり、farjmpが必要となるから
これは呼び出し部分
GotoV86 proc
pushad
pushr <fs, gs>
pushf
call ModeSwitch
popf
mov al, 3
out 0F6h, al ; force A20 OFF
popr
popad
ret
endp
480デフォルトの名無しさん
2019/11/01(金) 08:54:59.94ID:/dldU/F5 ModeSwitch proc
; call Enable4G
call SetAddress
call SetupIDT
call SetupTSS
xor eax, eax
mov es, ax
call CleanEMB ; これ以降、es=0
call SetupPageTable
call MoveCode
call Setup8259A
prefixd32 ;32bit gdtr (not 24bit gdtr)
lgdt GDTR
prefixd32 ;32bit idtr (not 24bit idtr)
lidt IDTR
mov eax, cr0
or eax, _PG + _PE ; 直接ページングをON
mov cr0, eax
jmp short $+2 ; flush queue
mov ax, GD_D_TSS ; タスクレジスタにダミーの設定
ltr ax
call VGtest
FLUSH GD_V_TSS ; jmp far seg, $next
ret
endp
最後に far jmpしてる
; call Enable4G
call SetAddress
call SetupIDT
call SetupTSS
xor eax, eax
mov es, ax
call CleanEMB ; これ以降、es=0
call SetupPageTable
call MoveCode
call Setup8259A
prefixd32 ;32bit gdtr (not 24bit gdtr)
lgdt GDTR
prefixd32 ;32bit idtr (not 24bit idtr)
lidt IDTR
mov eax, cr0
or eax, _PG + _PE ; 直接ページングをON
mov cr0, eax
jmp short $+2 ; flush queue
mov ax, GD_D_TSS ; タスクレジスタにダミーの設定
ltr ax
call VGtest
FLUSH GD_V_TSS ; jmp far seg, $next
ret
endp
最後に far jmpしてる
481デフォルトの名無しさん
2019/11/01(金) 08:56:48.06ID:x4OgavLA Super ASCIIに載ってたサンプルコード
https://pastebin.com/0Tk0U9Y1
(TASMで動作確認済み)
PC9801用のテストプログラム(VRAMを80808080で埋めてるだけです)
.386p
assume cs:prog,ds:prog
prog segment use16
org 100h
mov ah,40h
int 18h
mov ah,42h
mov ch,0c0h
int 18h
mov eax,0
mov es,ax
mov edi,0a8000h
mov ecx, 32768*3/4
mov eax, 80808080h
cld
db 67h
; use ecx for loop counter
rep stosd
mov ax,4c00h
int 21h
prog ends
end
https://pastebin.com/0Tk0U9Y1
(TASMで動作確認済み)
PC9801用のテストプログラム(VRAMを80808080で埋めてるだけです)
.386p
assume cs:prog,ds:prog
prog segment use16
org 100h
mov ah,40h
int 18h
mov ah,42h
mov ch,0c0h
int 18h
mov eax,0
mov es,ax
mov edi,0a8000h
mov ecx, 32768*3/4
mov eax, 80808080h
cld
db 67h
; use ecx for loop counter
rep stosd
mov ax,4c00h
int 21h
prog ends
end
482デフォルトの名無しさん
2019/11/01(金) 08:58:53.01ID:x4OgavLA サンプルコード、テストプログラムともにCOM形式なので
LINKした後にexe2bin protect.exe protect.comとcom形式に変換する必要があります
LINKした後にexe2bin protect.exe protect.comとcom形式に変換する必要があります
483デフォルトの名無しさん
2019/11/01(金) 11:55:34.87ID:iX6unUP8 知らない人が多いようなので書いておくと、
実測してみると pusha より、ばらばらの push 命令を書いたほうが速度が速い。
一つの理由は、push espという無駄なpushが1つ減らせるから。
これはQEMUなどを使っているだけでは分からない事実。
なお、こっちは良く知られたことだけど、enter, leave 命令より、
push ebp, mov ebp,esp, sub esp, nn などと書くほうが速い。
もっと言えば、486だとなぜかinc, dec が2クロック掛かってしまうのに、
add esp,1 や sub esp,1 は1クロックで済むという事実を知る人は少ないらしい。
実測してみると pusha より、ばらばらの push 命令を書いたほうが速度が速い。
一つの理由は、push espという無駄なpushが1つ減らせるから。
これはQEMUなどを使っているだけでは分からない事実。
なお、こっちは良く知られたことだけど、enter, leave 命令より、
push ebp, mov ebp,esp, sub esp, nn などと書くほうが速い。
もっと言えば、486だとなぜかinc, dec が2クロック掛かってしまうのに、
add esp,1 や sub esp,1 は1クロックで済むという事実を知る人は少ないらしい。
484デフォルトの名無しさん
2019/11/01(金) 11:58:53.09ID:iX6unUP8 >>483
補足。QEMU だと、pusha が1命令分の時間で済むのに対し、バラバラの
push命令に直してしまうと、その個数倍の時間が掛かるので、8倍程度後者
の方が遅い。実機だと、後者の方が16%程度速い。実機とQEMUでは全然
速度バランスが違うので、QEMUでの速度測定は全く参考にならないので注意。
補足。QEMU だと、pusha が1命令分の時間で済むのに対し、バラバラの
push命令に直してしまうと、その個数倍の時間が掛かるので、8倍程度後者
の方が遅い。実機だと、後者の方が16%程度速い。実機とQEMUでは全然
速度バランスが違うので、QEMUでの速度測定は全く参考にならないので注意。
485デフォルトの名無しさん
2019/11/01(金) 12:10:32.63ID:iX6unUP8 >>477
正確には short jmp だったか、far jump だったかは資料を見てみないと
思い出せないけど、少なくとも Wikibooksには、
6. Set the PE bit (and the PG bit if paging is going to be enabled) of the
MSW or CR0 register
7. Execute a far jump (in case of switching to long mode, even if the destination
code segment is a 64-bit code segment, the offset must not exceed 32-bit
since the far jump instruction is executed in compatibility mode)
また、https://stackoverflow.com/questions/26679682/how-does-setting-the-pe-flag-in-cr0-enable-protected-mode
にも、
1. Set up a global descriptor table (gdt) and load it using the lgdt instruction
2. Set the PE flag/bit in the control register CR0 to enabled (ie. to the value 1)
3. Execute a long jump with ljmp
Technically the CPU internally stores the selector information of all selectors used.
Whenever a selector register changes then the limit, base and so on are loaded.
This means that loading the CS register is required for updating the base, limit
and so of the CS register. This means: A far jump must be done (because this
will load the CS register). Maybe a RETF would also work...
I'm not sure if loading the other segment registers (for example DS) would
already work before the far jump so if you load the DS register before the
far jump the base address and limit will be taken from the GDT. Would be
nice to try this out...
と書かれている。
正確には short jmp だったか、far jump だったかは資料を見てみないと
思い出せないけど、少なくとも Wikibooksには、
6. Set the PE bit (and the PG bit if paging is going to be enabled) of the
MSW or CR0 register
7. Execute a far jump (in case of switching to long mode, even if the destination
code segment is a 64-bit code segment, the offset must not exceed 32-bit
since the far jump instruction is executed in compatibility mode)
また、https://stackoverflow.com/questions/26679682/how-does-setting-the-pe-flag-in-cr0-enable-protected-mode
にも、
1. Set up a global descriptor table (gdt) and load it using the lgdt instruction
2. Set the PE flag/bit in the control register CR0 to enabled (ie. to the value 1)
3. Execute a long jump with ljmp
Technically the CPU internally stores the selector information of all selectors used.
Whenever a selector register changes then the limit, base and so on are loaded.
This means that loading the CS register is required for updating the base, limit
and so of the CS register. This means: A far jump must be done (because this
will load the CS register). Maybe a RETF would also work...
I'm not sure if loading the other segment registers (for example DS) would
already work before the far jump so if you load the DS register before the
far jump the base address and limit will be taken from the GDT. Would be
nice to try this out...
と書かれている。
486デフォルトの名無しさん
2019/11/01(金) 12:19:54.06ID:iX6unUP8 >>485
だんだん思い出してきたので書いておくと、GDTRにGDTのアドレスをセットした
だけでは、CPU内部のセグメントレジスタの情報が更新されない。
例えば、dsには、リミット、ベースアドレスなどの情報がCPU内部に入っているが、
GDTRを更新した段階では、CPU内部のそれらの情報は更新されない。
更新されるのは、mov ds,ax や、pop ds, lds などを実行した場合のみ。
つまり、mov ds,ax などを実行して始めて、CPU内部のdsレジスタに関する隠れ
情報格納場所の情報までが更新され、dsにプロテクトモードらしいセグメントが
対応するようになる。
一方、csレジスタについては、mov cs,ax などの命令が無いので、その代わりになる
のが、far jmp ということになる。far ret や iret などでもいけるかもしれないが、
仕様上は far jmp ということになっているのだと思う。だから、プロテクトモードに
初めて突入したい場合に、far jmp 以外の命令でcs を更新した場合にどうなるかは
保証されていないかもしれない。
だんだん思い出してきたので書いておくと、GDTRにGDTのアドレスをセットした
だけでは、CPU内部のセグメントレジスタの情報が更新されない。
例えば、dsには、リミット、ベースアドレスなどの情報がCPU内部に入っているが、
GDTRを更新した段階では、CPU内部のそれらの情報は更新されない。
更新されるのは、mov ds,ax や、pop ds, lds などを実行した場合のみ。
つまり、mov ds,ax などを実行して始めて、CPU内部のdsレジスタに関する隠れ
情報格納場所の情報までが更新され、dsにプロテクトモードらしいセグメントが
対応するようになる。
一方、csレジスタについては、mov cs,ax などの命令が無いので、その代わりになる
のが、far jmp ということになる。far ret や iret などでもいけるかもしれないが、
仕様上は far jmp ということになっているのだと思う。だから、プロテクトモードに
初めて突入したい場合に、far jmp 以外の命令でcs を更新した場合にどうなるかは
保証されていないかもしれない。
487デフォルトの名無しさん
2019/11/02(土) 18:02:51.42ID:cEPd2nC/ 低レベルな相談です
ADDL・ADDA・SUBL・SUBA・AND・OR・XOR・CPL・CPA命令において
オペランドの第2引数に、=を付けるのをつい忘れてしまうんですが、
何か対処法はありますか?
ADDL・ADDA・SUBL・SUBA・AND・OR・XOR・CPL・CPA命令において
オペランドの第2引数に、=を付けるのをつい忘れてしまうんですが、
何か対処法はありますか?
488デフォルトの名無しさん
2019/11/02(土) 22:19:49.20ID:dJ3V2vrm >>487
CASL II は始めて見たんだけど、
http://masudahp.web.fc2.com/casl2/casl2110.html
http://masudahp.web.fc2.com/casl2/casl2120.html
ADDA GR0, =#0045
のように書くと、自動的にラベルを生成して、
ADDA GR0, DATA1
・・・
DATA1 DC #0045
と書いたの等価になるらしいから、忘れるとか言う問題ではなく、
CASL II言語の基礎なので自然に覚えるしかないですね。
アセンブリプログラミングには、このくらいの記憶力は必要です。
ただ、丸覚えするのではなく、ちゃんと理解すれば自然に覚えられると思います。
CASL II は始めて見たんだけど、
http://masudahp.web.fc2.com/casl2/casl2110.html
http://masudahp.web.fc2.com/casl2/casl2120.html
ADDA GR0, =#0045
のように書くと、自動的にラベルを生成して、
ADDA GR0, DATA1
・・・
DATA1 DC #0045
と書いたの等価になるらしいから、忘れるとか言う問題ではなく、
CASL II言語の基礎なので自然に覚えるしかないですね。
アセンブリプログラミングには、このくらいの記憶力は必要です。
ただ、丸覚えするのではなく、ちゃんと理解すれば自然に覚えられると思います。
489デフォルトの名無しさん
2019/11/02(土) 22:41:38.43ID:dJ3V2vrm >>488
実際のCASL IIがそう書けるかどうかはともかくとして、
数学記号と同様の感覚で記号の対応関係や「類推(推論)」で考えれば、
ADDA GR0,#0045
と書くと、アドレス #0045 番地のメモリーに入っている内容を読み出した値を
GR0に足す、という意味になります。# は以後の数値が16進数である事を表す
記号です。初めに言ったようにこの書き方がCASL II 言語で実際に出来るか
どうかは分かりませんが、意味で考えるとそういう意味になるでしょう。一方、
ADDA GR0,=#0045
は、>>488 に書いたように、0045 という16進数の値を入れた領域を
自動的に確保して、そのアドレスを xxx とすると、自動的にその場所を
ADDA GR0,xxx
という命令に置き換えるという意味です。
かなり違う意味です。ですから、覚える覚えないの話では無い事が分かります。
実際のCASL IIがそう書けるかどうかはともかくとして、
数学記号と同様の感覚で記号の対応関係や「類推(推論)」で考えれば、
ADDA GR0,#0045
と書くと、アドレス #0045 番地のメモリーに入っている内容を読み出した値を
GR0に足す、という意味になります。# は以後の数値が16進数である事を表す
記号です。初めに言ったようにこの書き方がCASL II 言語で実際に出来るか
どうかは分かりませんが、意味で考えるとそういう意味になるでしょう。一方、
ADDA GR0,=#0045
は、>>488 に書いたように、0045 という16進数の値を入れた領域を
自動的に確保して、そのアドレスを xxx とすると、自動的にその場所を
ADDA GR0,xxx
という命令に置き換えるという意味です。
かなり違う意味です。ですから、覚える覚えないの話では無い事が分かります。
490デフォルトの名無しさん
2019/11/02(土) 22:47:11.43ID:dJ3V2vrm >>489
x86アセンブラを知っている人ならば、
ADDA GR0,GR1 ---> mov GR0,dword ptr [GR1]
ADDA GR0,#0045 ---> mov GR0,dword ptr [0045h]
ADDA GR0,=#0045 ---> mov GR0,0045h
また、C言語を知っている人ならば、
ADDA GR0,GR1 ---> GR0 += *(DWORD *)GR1;
ADDA GR0,#0045 ---> GR0 += *(DWORD *)0x0045;
ADDA GR0,=#0045 ---> GR0 += 0x0045;
となります。
対応関係は、第二オペランドに X を書くと、[X] や、*X の意味になり、
=X と書くと、X の意味になります。
x86アセンブラを知っている人ならば、
ADDA GR0,GR1 ---> mov GR0,dword ptr [GR1]
ADDA GR0,#0045 ---> mov GR0,dword ptr [0045h]
ADDA GR0,=#0045 ---> mov GR0,0045h
また、C言語を知っている人ならば、
ADDA GR0,GR1 ---> GR0 += *(DWORD *)GR1;
ADDA GR0,#0045 ---> GR0 += *(DWORD *)0x0045;
ADDA GR0,=#0045 ---> GR0 += 0x0045;
となります。
対応関係は、第二オペランドに X を書くと、[X] や、*X の意味になり、
=X と書くと、X の意味になります。
491デフォルトの名無しさん
2019/11/02(土) 22:48:31.37ID:dJ3V2vrm >>490
すみません、movとaddを書き間違えました。正しくはこうです。:
x86アセンブラを知っている人ならば、
ADDA GR0,GR1 ---> add GR0,dword ptr [GR1]
ADDA GR0,#0045 ---> add GR0,dword ptr [0045h]
ADDA GR0,=#0045 ---> add GR0,0045h
すみません、movとaddを書き間違えました。正しくはこうです。:
x86アセンブラを知っている人ならば、
ADDA GR0,GR1 ---> add GR0,dword ptr [GR1]
ADDA GR0,#0045 ---> add GR0,dword ptr [0045h]
ADDA GR0,=#0045 ---> add GR0,0045h
493デフォルトの名無しさん
2019/11/12(火) 18:31:03.25ID:m5a+lCw/ マイコン用のアセンブラコードジェネレータを作りたいんだけどどんな感じにするのが良いんだろうか
if文で条件分岐させていくとコード生成部が条件分岐だらけになって訳が判らなくなる
組み込み用なのでパイプラインのストールを引き起こすようなコードはなるべく生成したくない
if文で条件分岐させていくとコード生成部が条件分岐だらけになって訳が判らなくなる
組み込み用なのでパイプラインのストールを引き起こすようなコードはなるべく生成したくない
494デフォルトの名無しさん
2019/11/12(火) 18:53:07.41ID:I0vQskxn bison+flex+LLVM
495デフォルトの名無しさん
2019/11/12(火) 23:09:55.20ID:We/BiDY5 >>493
テーブル参照して引っ張ってくるのが一番楽かと
テーブル参照して引っ張ってくるのが一番楽かと
496デフォルトの名無しさん
2019/11/13(水) 01:29:11.05ID:6OGWlygT やる気だけでは進まない
497493
2019/11/13(水) 08:08:30.10ID:HNnV6bHC ありがとう
>>494
判りにくくてスマン。ガチの処理系を作りたいわけではないんだ
チップメーカーが出しているGUIでパラメータをポチポチ設定してGeneratボタンをクリックすると
設定に従ったライブラリコードを自動生成してくれるみたいな奴を作りたい
というかLLVMとかは自分の手におえそうにない
>>495
ハッシュテーブルみたいな感じ?パターンは結構ある
今考えているパラメータだけでも
書き込み先アドレスが〜30種程度と〜10種類程度×2
処理の選択にbool値が5個くらい、サイクル数指定が3種
サイクル数を指定できる区間は重なっているし結構ややこしい
ちょっと前から作り始めているけどすでにぐちゃぐちゃ・・・
>>494
判りにくくてスマン。ガチの処理系を作りたいわけではないんだ
チップメーカーが出しているGUIでパラメータをポチポチ設定してGeneratボタンをクリックすると
設定に従ったライブラリコードを自動生成してくれるみたいな奴を作りたい
というかLLVMとかは自分の手におえそうにない
>>495
ハッシュテーブルみたいな感じ?パターンは結構ある
今考えているパラメータだけでも
書き込み先アドレスが〜30種程度と〜10種類程度×2
処理の選択にbool値が5個くらい、サイクル数指定が3種
サイクル数を指定できる区間は重なっているし結構ややこしい
ちょっと前から作り始めているけどすでにぐちゃぐちゃ・・・
498デフォルトの名無しさん
2019/11/21(木) 00:03:41.36ID:Sj//p0Te 初歩的な質問です
8086とZ80だったらどっちを勉強した方が良いですか?
8086とZ80だったらどっちを勉強した方が良いですか?
499デフォルトの名無しさん
2019/11/21(木) 01:21:24.28ID:FiaSI4dm 8086
500デフォルトの名無しさん
2019/11/21(木) 01:21:54.93ID:FiaSI4dm x64じゃいかんの?
501デフォルトの名無しさん
2019/11/21(木) 02:11:07.86ID:dnQ3Bqh9 z80だろ
502デフォルトの名無しさん
2019/11/21(木) 02:13:40.22ID:dnQ3Bqh9 >>498
やっぱ両方いらん
やっぱ両方いらん
503デフォルトの名無しさん
2019/11/21(木) 05:15:38.34ID:1McLuuYz すでに何かのアセンブラ理解してるなら両方勉強しても数日で理解できるだろう。
はじめてアセンブラ勉強するならそりゃシンプルな8bitCPUで圧倒的に情報が多いZ80だろうな。
はじめてアセンブラ勉強するならそりゃシンプルな8bitCPUで圧倒的に情報が多いZ80だろうな。
504498
2019/11/22(金) 00:24:30.25ID:I5J2JfnT 返信が遅くなってすいません
答えて頂いた方、ありがとうございました
答えて頂いた方、ありがとうございました
505デフォルトの名無しさん
2019/11/22(金) 13:34:09.59ID:zKQgPoBc マジレスするとアセンブラを使う目的次第
PICやRL78みたいな小規模でCPUや電子回路を学ぶ
x64で高速化やSIMDを試す
ラズベリーパイやスマホのARMで遊んでみる
DSPで信号処理やフィードバック制御を学ぶ
など
PICやRL78みたいな小規模でCPUや電子回路を学ぶ
x64で高速化やSIMDを試す
ラズベリーパイやスマホのARMで遊んでみる
DSPで信号処理やフィードバック制御を学ぶ
など
506デフォルトの名無しさん
2019/11/22(金) 15:29:17.71ID:gUUFthXr >>498
6809
6809
507デフォルトの名無しさん
2019/11/22(金) 16:26:18.45ID:2jFqraTL508デフォルトの名無しさん
2019/11/22(金) 16:34:56.93ID:2jFqraTL >>507
ちなみに、CPUとしては両者は親戚みたいなもので、Z80を学んだ後から、
8086へ進んでも文化に共通点が多いので理解し易い。
たとえば、条件分岐は、cmpなどの比較命令を実行して
zero flag や carry flag などに影響を与えた後に、Jcc 命令を使う点や、
cmp以外にsubやaddでも全く同様に zero flag, carry flag などに影響を
与えると言う点が両者で共通している。
他のCPUでは全く違うやり方をとるものも多い。
ところが、Z80は8BIT CPU としてはとても上手くできていた方だが、
8086は、16BIT CPU としては残念な方であった。一つの理由は、
当時は低価格で理想的な16BIT CPUを作るためには、ICにおけるトランジスタの
集積度が不足していたが、8BIT CPUを作るには十分であったためらしい。
なので、8BIT CPUは使い易いものが作れたが、16BIT CPU は使いにくいもの
しか作れなかった、と考えることが出来る。
ちなみに、CPUとしては両者は親戚みたいなもので、Z80を学んだ後から、
8086へ進んでも文化に共通点が多いので理解し易い。
たとえば、条件分岐は、cmpなどの比較命令を実行して
zero flag や carry flag などに影響を与えた後に、Jcc 命令を使う点や、
cmp以外にsubやaddでも全く同様に zero flag, carry flag などに影響を
与えると言う点が両者で共通している。
他のCPUでは全く違うやり方をとるものも多い。
ところが、Z80は8BIT CPU としてはとても上手くできていた方だが、
8086は、16BIT CPU としては残念な方であった。一つの理由は、
当時は低価格で理想的な16BIT CPUを作るためには、ICにおけるトランジスタの
集積度が不足していたが、8BIT CPUを作るには十分であったためらしい。
なので、8BIT CPUは使い易いものが作れたが、16BIT CPU は使いにくいもの
しか作れなかった、と考えることが出来る。
509デフォルトの名無しさん
2019/11/22(金) 16:45:49.82ID:gUUFthXr 80186 で恥の上塗りですね判ります
510デフォルトの名無しさん
2019/11/22(金) 16:56:01.19ID:2jFqraTL >>508
他にも、
1. 両者とも、アラインの揃ってないアドレスからでも16BIT以上のデータを
読み出せると言う特徴がある。これが出来ないCPUも多く、Apple系は昔そういう
CPUを使っていたと聞いている。今でもC言語の構造体などで align が細々と
決まっているのは、後者の文化圏の人達が主導しているのかも知れない。
2. carry flag(8086 では「borrow flag」という名前になっている)を使うと、
多倍長の加減算が容易に出来るのも両社に共通している。この特徴は、
他のCPUには無いことが多いらしい。だから、LLVMなどには adc や sbc(sbb)
相当の命令が無いし、carry flag を捕捉する命令も定義されていない。
3. LLVM では、単純な引き算の延長線上にある cmp 命令でフラグを作った後、
条件の種類によっていろいろな種類のJcc で条件分岐するという流儀をとっておらず、
条件の種類によって比較命令自体を変えてしまって、結果は常に 1BIT の
BOOL値とし。逆に Jcc 命令は原則一種類となっている。これは、LLVMが
Z80や8086とは異なる文化圏の人が作ったものであるのではないかと推定される。
4.アカデミカルな世界では、CPUとして、業界事実標準の Z80 や 8086 系統ではなく、
どうも違う文化のものを想定していることが多い気がする。
色々な言葉が、Z80 や 8086 ではかなり多く共通しているが、LLVMとは全く
違う。
他にも、
1. 両者とも、アラインの揃ってないアドレスからでも16BIT以上のデータを
読み出せると言う特徴がある。これが出来ないCPUも多く、Apple系は昔そういう
CPUを使っていたと聞いている。今でもC言語の構造体などで align が細々と
決まっているのは、後者の文化圏の人達が主導しているのかも知れない。
2. carry flag(8086 では「borrow flag」という名前になっている)を使うと、
多倍長の加減算が容易に出来るのも両社に共通している。この特徴は、
他のCPUには無いことが多いらしい。だから、LLVMなどには adc や sbc(sbb)
相当の命令が無いし、carry flag を捕捉する命令も定義されていない。
3. LLVM では、単純な引き算の延長線上にある cmp 命令でフラグを作った後、
条件の種類によっていろいろな種類のJcc で条件分岐するという流儀をとっておらず、
条件の種類によって比較命令自体を変えてしまって、結果は常に 1BIT の
BOOL値とし。逆に Jcc 命令は原則一種類となっている。これは、LLVMが
Z80や8086とは異なる文化圏の人が作ったものであるのではないかと推定される。
4.アカデミカルな世界では、CPUとして、業界事実標準の Z80 や 8086 系統ではなく、
どうも違う文化のものを想定していることが多い気がする。
色々な言葉が、Z80 や 8086 ではかなり多く共通しているが、LLVMとは全く
違う。
511デフォルトの名無しさん
2019/11/22(金) 17:05:38.22ID:zKQgPoBc まあ普通にx64かARMかMIPS
ARMやMIPSはもともとRISCなので非常にきれいでシンプル
x64はAVXなどのリッチな命令を楽しめるし
環境もPCにVisual Studioを入れるだけ
ARMやMIPSはもともとRISCなので非常にきれいでシンプル
x64はAVXなどのリッチな命令を楽しめるし
環境もPCにVisual Studioを入れるだけ
512デフォルトの名無しさん
2019/11/22(金) 17:09:00.41ID:zKQgPoBc 80186(改)は実はわりと最近まで製品で使ってましたよ
大きなLSIの中に、制御用にコアだけ入ってるやつ
セグメントレジスタが4シフトではなく8シフト
大きなLSIの中に、制御用にコアだけ入ってるやつ
セグメントレジスタが4シフトではなく8シフト
513デフォルトの名無しさん
2019/11/22(金) 17:10:09.89ID:omZwaM5I >>510
シッタカで出鱈目書くなよ糞が
シッタカで出鱈目書くなよ糞が
514デフォルトの名無しさん
2019/11/22(金) 17:11:44.26ID:zKQgPoBc すいません
515デフォルトの名無しさん
2019/11/22(金) 17:11:56.78ID:zKQgPoBc おれじゃなかった
516デフォルトの名無しさん
2019/11/22(金) 17:54:18.76ID:UNbCtceI517デフォルトの名無しさん
2019/11/22(金) 18:28:01.42ID:hDmJhEnO >>510じゃないけど
1.性能上(もしくはアトミック性)の理由でアラインメントを揃える
2.8086でもキャリーフラグという名前
もちろんボローの意味でも使う
フラグはOut Of Orderの妨げになりやすく
シンプルな設計を目指したRISC系では使わないし
当然SIMDでも使わない
ただし、命令を組み合わせて同じことが出来る
多倍長の加減算は(乗算他に比べて)速いので
それが性能に影響することは少ないし
64bit CPUではそもそも64bitを越えた演算をすることも非常に少ない
1.性能上(もしくはアトミック性)の理由でアラインメントを揃える
2.8086でもキャリーフラグという名前
もちろんボローの意味でも使う
フラグはOut Of Orderの妨げになりやすく
シンプルな設計を目指したRISC系では使わないし
当然SIMDでも使わない
ただし、命令を組み合わせて同じことが出来る
多倍長の加減算は(乗算他に比べて)速いので
それが性能に影響することは少ないし
64bit CPUではそもそも64bitを越えた演算をすることも非常に少ない
518デフォルトの名無しさん
2019/11/22(金) 18:29:07.76ID:hDmJhEnO519デフォルトの名無しさん
2019/11/22(金) 18:33:09.28ID:hDmJhEnO 4.z80はまったく業界標準ではないですね
数量から言えばARMとx86系が圧倒的
MIPSは教育現場では使われるけど
数量はARMやx86系に比べたら少ない
x86も16bit命令で組む事はほぼない
32bitか64bitがほとんど
数量から言えばARMとx86系が圧倒的
MIPSは教育現場では使われるけど
数量はARMやx86系に比べたら少ない
x86も16bit命令で組む事はほぼない
32bitか64bitがほとんど
520デフォルトの名無しさん
2019/11/22(金) 18:35:52.35ID:hDmJhEnO あとは教育だとRISC-Vとか
521デフォルトの名無しさん
2019/11/22(金) 18:35:58.82ID:z6OUhbA9 ARM系の条件分岐ってフラグベースじゃね?
522デフォルトの名無しさん
2019/11/22(金) 18:43:24.01ID:LRWcxGhp いまどき初心者がZ80に興味持つはずないだろ
こいつが御高説を垂れたいがために質問を自演してるんだろ
情けない奴
こいつが御高説を垂れたいがために質問を自演してるんだろ
情けない奴
523デフォルトの名無しさん
2019/11/22(金) 19:07:15.94ID:sA8M4Dff Z80そのものが使われる機会は減っていてもZ80の流れを汲むアーキテクチャはまだまだある
IA32/AMD64はもちろん、ちょっと上であがっているRL78もだ
IA32/AMD64はもちろん、ちょっと上であがっているRL78もだ
524デフォルトの名無しさん
2019/11/22(金) 19:10:46.49ID:hDmJhEnO525デフォルトの名無しさん
2019/11/22(金) 19:26:38.06ID:sA8M4Dff 組み込み系でも8bitだと桁上がり演算でキャリーをよく使うけど32bitだと出番は激減する
32bitあれば12bitADCの変換値を10回足し込むくらいじゃ余裕
一部のアーキテクチャは特殊演算用に64bitを超えるレジスタを持っていたりするし
なおさら桁あふれしにくい
32bitあれば12bitADCの変換値を10回足し込むくらいじゃ余裕
一部のアーキテクチャは特殊演算用に64bitを超えるレジスタを持っていたりするし
なおさら桁あふれしにくい
526デフォルトの名無しさん
2019/11/22(金) 20:20:02.18ID:LRWcxGhp >>523
ID変えて否定に回ったのが自演の証拠w
ID変えて否定に回ったのが自演の証拠w
527デフォルトの名無しさん
2019/11/22(金) 21:52:14.02ID:DXtwsE0I Intel系のCPUは元々4bitの4004から来ている。4004は主に電卓で使われた。4bitレジスタで演算するとき
桁あふれが頻繁に起こるのがわかっていたのでキャリーフラグがあると便利だろうということで入れたんだと思う。
それが8bitの8008以降も継承されて現在に至る。だから64bitでキャリーフラグが使われないのも当然。
桁あふれが頻繁に起こるのがわかっていたのでキャリーフラグがあると便利だろうということで入れたんだと思う。
それが8bitの8008以降も継承されて現在に至る。だから64bitでキャリーフラグが使われないのも当然。
528デフォルトの名無しさん
2019/11/22(金) 22:00:58.35ID:uBbdr9rC 最後の「だから」がなぜ「だから」なのかわからない
529デフォルトの名無しさん
2019/11/22(金) 22:22:56.50ID:2jFqraTL >>517
>ただし、命令を組み合わせて同じことが出来る
一年ほど前に調べていたら、x+y に対するキャリーフラグをC言語を使って
作り出すようなことを書いているコードを見つけた。
普通に考えればx,yの最上位ビットに着目すればいいんだけど、
最初に思いつくコードよりかなり短いコードだった。
x,yが8BITの場合、x+yに対するキャリーフラグをcfとすると、
意味的には、
cf = 0;
if ( (x & 0x80) != 0 && (y & 0x80) != 0 ) {
cf = 1;
}
でいいはずだけど、
cf = (x & y) >> 7;
かな。でも、もっとエレガントなコードだったような気がする。
何か知っていれば教えて欲しい。
>ただし、命令を組み合わせて同じことが出来る
一年ほど前に調べていたら、x+y に対するキャリーフラグをC言語を使って
作り出すようなことを書いているコードを見つけた。
普通に考えればx,yの最上位ビットに着目すればいいんだけど、
最初に思いつくコードよりかなり短いコードだった。
x,yが8BITの場合、x+yに対するキャリーフラグをcfとすると、
意味的には、
cf = 0;
if ( (x & 0x80) != 0 && (y & 0x80) != 0 ) {
cf = 1;
}
でいいはずだけど、
cf = (x & y) >> 7;
かな。でも、もっとエレガントなコードだったような気がする。
何か知っていれば教えて欲しい。
530デフォルトの名無しさん
2019/11/22(金) 22:28:55.69ID:2jFqraTL さらに、x, y が符号なし8BIT整数の場合の x - y に対する carry flag については、
cf = 0;
if ( x < y ) cf = 1;
で一応求まるんだと思う。
また、sf(sign flag) に関しては、
sf = 演算結果 >> 7;
でいいと思われる。
cf = 0;
if ( x < y ) cf = 1;
で一応求まるんだと思う。
また、sf(sign flag) に関しては、
sf = 演算結果 >> 7;
でいいと思われる。
531デフォルトの名無しさん
2019/11/22(金) 22:33:04.48ID:2jFqraTL532デフォルトの名無しさん
2019/11/22(金) 22:40:25.25ID:2jFqraTL533デフォルトの名無しさん
2019/11/22(金) 22:46:49.23ID:2jFqraTL >>532
すまん。後半部は間違いらしい。
すまん。後半部は間違いらしい。
534デフォルトの名無しさん
2019/11/22(金) 23:19:09.49ID:2jFqraTL535デフォルトの名無しさん
2019/11/23(土) 00:09:22.51ID:zs0Ad1fs >>528
64bitレジスタでは4bitレジスタに比べて桁あふれが起きにくいから使用頻度が少なくなる。
64bitレジスタでは4bitレジスタに比べて桁あふれが起きにくいから使用頻度が少なくなる。
536デフォルトの名無しさん
2019/11/23(土) 02:42:52.78ID:eMnkZzKn 足し算
z0 = x0+y0;
z1 = x1+y1+(z0<x0);
引き算
z0 = x0-y0;
z1 = x1-y1-(z0>x0);
z0 = x0+y0;
z1 = x1+y1+(z0<x0);
引き算
z0 = x0-y0;
z1 = x1-y1-(z0>x0);
537デフォルトの名無しさん
2019/11/23(土) 03:01:11.70ID:eMnkZzKn carry = 0;
for (i=0 ; i < n ; i++){
. . if (carry){
. . . . z[i] = x[i] + y[i];
. . . . carry = z[i] < x[i];
. . }
. . else {
. . . . z[i] = x[i] + y[i] + 1;
. . . . carry = z[i] <= x[i];
. . }
}
for (i=0 ; i < n ; i++){
. . if (carry){
. . . . z[i] = x[i] + y[i];
. . . . carry = z[i] < x[i];
. . }
. . else {
. . . . z[i] = x[i] + y[i] + 1;
. . . . carry = z[i] <= x[i];
. . }
}
538デフォルトの名無しさん
2019/11/23(土) 03:03:32.41ID:eMnkZzKn borrow = 0;
for (i=0 ; i < n ; i++){
. . if (carry){
. . . . z[i] = x[i] - y[i];
. . . . borrow = z[i] > x[i];
. . }
. . else {
. . . . z[i] = x[i] - y[i] - 1;
. . . . borrow = z[i] >= x[i];
. . }
}
for (i=0 ; i < n ; i++){
. . if (carry){
. . . . z[i] = x[i] - y[i];
. . . . borrow = z[i] > x[i];
. . }
. . else {
. . . . z[i] = x[i] - y[i] - 1;
. . . . borrow = z[i] >= x[i];
. . }
}
539529
2019/11/23(土) 11:50:40.96ID:U8iKLMmJ 自己訂正です。
実は、色々と間違いがあり、次のようになっています:
>>529 : 間違い。
530 : 正しい。
531 : 正しい。
>>532 の前半 : 正しい。
>>532 の後半 : 間違い。
改めて、>>529 の根本的な間違いとして、carry flag は、演算前の最上位ビットだけでは決まる、
というのが大間違いでした。下位ビットからの桁上がりがあるためです。
まとめると、x, y が符号なし整数の場合、
1. a = x - y に対する carry flag :
cf = (x < y);
または。
cf = (a > x);
2. a = x + y に対する carry flag :
cf = (x < (-y));
または。
cf = (a < x);
です。上記の「または」以後のやり方は、>>536 537 538 で思い出させていただきました。
一年ほど前に見たやり方がそれだったと思います。とてもエレガントですね。
実は、色々と間違いがあり、次のようになっています:
>>529 : 間違い。
530 : 正しい。
531 : 正しい。
>>532 の前半 : 正しい。
>>532 の後半 : 間違い。
改めて、>>529 の根本的な間違いとして、carry flag は、演算前の最上位ビットだけでは決まる、
というのが大間違いでした。下位ビットからの桁上がりがあるためです。
まとめると、x, y が符号なし整数の場合、
1. a = x - y に対する carry flag :
cf = (x < y);
または。
cf = (a > x);
2. a = x + y に対する carry flag :
cf = (x < (-y));
または。
cf = (a < x);
です。上記の「または」以後のやり方は、>>536 537 538 で思い出させていただきました。
一年ほど前に見たやり方がそれだったと思います。とてもエレガントですね。
540デフォルトの名無しさん
2019/11/25(月) 14:32:25.64ID:1+9AnSdf MIPS64やRISC-VのRV64Iで128bit加算減算のアセンブラ出力してみると
おなじようなことやってるね
mips64 128bit加算 $4:$2 ← $5:$4 + $7:$6
daddu $2,$4,$6
sltu $8,$2,$4
dext $8,$8,0,32
daddu $3,$5,$7
daddu $4,$8,$3
mips64 128bit減算 $4:$2 ← $5:$4 - $7:$6
dsubu $2,$4,$6
sltu $8,$4,$2
dext $8,$8,0,32
dsubu $3,$5,$7
dsubu $4,$3,$8
risc-v RV64I 128bit加算 a6:a7 ← a1:a0 + a3:a2
add a7,a0,a2
sltu a6,a7,a0
add t1,a1,a3
add a6,a6,t1
risc-v RV64I 128bit減算 a1:a2 ← a1:a0 - a3:a2
sub a2,a0,a2
sgtu a0,a2,a0
sub a1,a1,a3
sub a1,a1,a0
おなじようなことやってるね
mips64 128bit加算 $4:$2 ← $5:$4 + $7:$6
daddu $2,$4,$6
sltu $8,$2,$4
dext $8,$8,0,32
daddu $3,$5,$7
daddu $4,$8,$3
mips64 128bit減算 $4:$2 ← $5:$4 - $7:$6
dsubu $2,$4,$6
sltu $8,$4,$2
dext $8,$8,0,32
dsubu $3,$5,$7
dsubu $4,$3,$8
risc-v RV64I 128bit加算 a6:a7 ← a1:a0 + a3:a2
add a7,a0,a2
sltu a6,a7,a0
add t1,a1,a3
add a6,a6,t1
risc-v RV64I 128bit減算 a1:a2 ← a1:a0 - a3:a2
sub a2,a0,a2
sgtu a0,a2,a0
sub a1,a1,a3
sub a1,a1,a0
541デフォルトの名無しさん
2019/11/25(月) 18:08:28.75ID:FcoOoav6 だろうね
542デフォルトの名無しさん
2019/11/28(木) 08:12:36.09ID:xy0IaHJE543デフォルトの名無しさん
2019/11/28(木) 08:14:06.75ID:xy0IaHJE MIPS以降の多くのRISCベースのCPUはすべてキャリーフラグがある。
とても効率的で不可欠だからだ。
とても効率的で不可欠だからだ。
544デフォルトの名無しさん
2019/11/28(木) 19:38:36.20ID:jGkkl6Qu545デフォルトの名無しさん
2019/11/28(木) 19:56:47.34ID:PoPpbfsh フラグはアウトオブオーダーの妨げになるし
並列化も出来ないから
高速化に対してはイマイチ
並列化も出来ないから
高速化に対してはイマイチ
■ このスレッドは過去ログ倉庫に格納されています
ニュース
- 「おこめ券は米以外の食品も買える。効果的な活用を」 地元で農水相 [山形県] [少考さん★]
- 高市首相の答弁書に「台湾有事答えない」と明記 存立危機発言当時 ★11 [蚤の市★]
- 【速報】「女芸人No.1決定戦 THE W」9代目女王にニッチェ! 7年ぶり3度目で悲願の優勝 [牛丼★]
- 【芸能】『女芸人No.1決定戦THE W』 粗品が最後にバッサリ「優勝賞金1000万円にしてはレベル低い大会」 [冬月記者★]
- 【沖縄】開業4ヵ月でこれは…“国民の税金”投入の『ジャングリア沖縄』で見た衝撃的な光景と、モチベーションが低い一部スタッフの現状 [ぐれ★]
- 【東京】「家族で話題にして」 “世田谷一家殺害から25年 警視庁が呼びかけ [煮卵★]
- クズ「勉強頑張らなかった奴は一生DQNと一緒に肉体労働しろ」☚勉強頑張れるのも環境と巡り合わせなんだが? [783475554]
- ( ・᷇ὢ・᷆ )朝ごはん食べた?
- 俺の口癖が「へー」「そう」「どうも」なんだが
- 【時事】立憲民主党、30代の支持率が「ゼロ」😨 [369521721]
- うふ~ん♥死にたいわ~ん♥
- 加藤純一です
