17/04/13 17:35:55.70 1WMn3pSz.net
初心者OK!質問大歓迎!のアセンブラのスレッドです。
基本情報の勉強中の人、PICやH8を勉強中の学生などなど…
前スレ
アセンブラ初心者スレッド
スレリンク(tech板)
関連スレ
アセンブラ 13
スレリンク(tech板)
2:デフォルトの名無しさん
17/04/13 17:41:03.83 m/ZfxtWH.net
>>1
乙
3:デフォルトの名無しさん
17/04/13 18:14:24.24 VLmLig3K.net
v3
4:あぼーん
17/04/13 18:15:04.12 Gon4S40X.net
あぼーん
5:デフォルトの名無しさん
17/04/13 18:15:32.34 VLmLig3K.net
終了
6: ◆QZaw55cn4c
17/04/13 19:36:20.78 RYqONwMZ.net
きょうびの時代にアセンブラの優位性を主張する,とすれば
どのような分野で有効でしょうか?
7:デフォルトの名無しさん
17/04/13 19:43:03.43 VLmLig3K.net
asm.js とかさ
LLVM とかさ
このスレで扱っても良いと思うのね
8:デフォルトの名無しさん
17/04/13 20:44:33.86 nESB199J.net
ごもっともですわ
9:デフォルトの名無しさん
17/04/13 21:26:38.34 J4z4l4hW.net
うん需要ある?
10:デフォルトの名無しさん
17/04/14 08:40:42.32 sKcRbeeD.net
組み込みでなら多少は。
11:デフォルトの名無しさん
17/04/14 10:04:28.48 L6e5ZQwW.net
あ。。。IoTとか?
12:デフォルトの名無しさん
17/04/15 04:12:03.81 2Mj3RTtW.net
アセンブラはじめるならLinuxでやるといいよ
DOSと同じような感覚でアセンブラプログラミングができるから
こんな感じ
Linux でアセンブリプログラミング
URLリンク(www.mztn.org)
Linux で64bitアセンブリプログラミング
URLリンク(www.mztn.org)
Linuxでのアセンブル方法はこんな感じ
as -a=hogehoge.lst -o hogehoge.o hogehoge.s
ld -o hogehoge hogehoge.s
gccのでアセンブラ出力&アセンブル
gcc -S -o hogehoge.s hogehoge.c
as -a=hogehoge.lst -o hogehoge.o hogehoge.s
gcc -o hogehoge hogehoge.o
13:デフォルトの名無しさん
17/04/15 04:12:41.23 2Mj3RTtW.net
ちなみにx86_64上のLinuxで32bitのバイナリを作成したい場合はこう
x86_64のLinuxでのCの32bitのx86バイナリのコンパイル
gcc -m32 -O2 -o hogehoge hogehoge.c
x86_64のLinuxでの32bitのx86アセンブル
as --32 -a=hogehoge.lst -o hogehoge.o hogehoge.s
ld -melf_i386 -o hogehoge hogehoge.o
x86_64のLinuxでのgccので32bitアセンブラ出力&アセンブル
gcc -m32 -S -o hogehoge.s hogehoge.c
as --32 -a=hogehoge.lst -o hogehoge.o hogehoge.s
gcc -m32 -o hogehoge hogehoge.o
14:デフォルトの名無しさん
17/04/15 04:13:21.76 2Mj3RTtW.net
nasmでのx86_64のLinuxでの32bitアセンブル
nasm -f elf hogehoge.s
ld -melf_i386 -o hogehoge hogehoge.o
nasmでのx86_64のLinuxでの64bitアセンブル
nasm -f elf64 $1.s
ld -o $1 $1.o
Ubuntuでのnasmのインストール方法
sudo apt-get install nasm
15:デフォルトの名無しさん
17/04/15 04:42:00.93 2Mj3RTtW.net
UbuntuだとQEMUを入れるだけでQEMU+binfmtの設定が自動せされるから
ライブラリへのリンクを貼るだけで他のCPUのバイナリをそのまま実行できるようになる
UbuntuだとARM、MIPS、PowerPCができる
64bitARMならこんな感じ
sudo apt-get install qemu
sudo apt-get install g++-aarch64-linux-gnu
sudo ln -s /usr/aarch64-linux-gnu/lib/ld-linux-aarch64.so.1 /lib
sudo ln -s /usr/aarch64-linux-gnu/lib /lib/aarch64-linux-gnu
32bitARMならこんな感じ
sudo apt-get install qemu
sudo apt-get install g++-arm-linux-gnueabihf
sudo ln -s /usr/arm-linux-gnueabihf/lib/ld-linux-armhf.so.3 /lib
sudo ln -s /usr/arm-linux-gnueabihf/lib /lib/arm-linux-gnueabihf
Cのコンパイル方法はこんな感じ
aarch64-linux-gnu-gcc -O2 -o hogehoge hogehoge.c
arm-linux-gnueabihf-gcc -O2 -o hogehoge hogehoge.c
数学ライブラリを使う場合のCのコンパイル方法はこんな感じ
aarch64-linux-gnu-gcc -O2 -o hogehoge hogehoge.c -lm
(Ubuntuでは依存するライブラリを後ろに書く)
arm-linux-gnueabihf-gcc -O2 -o hogehoge hogehoge.c -lm
16:デフォルトの名無しさん
17/04/15 04:43:20.47 2Mj3RTtW.net
アセンブル方法はこんな感じ
aarch64-linux-gnu-as -a=hogehoge.lst -o hogehoge.o hogehoge.s
aarch64-linux-gnu-ld -o hogehoge hogehoge.s
arm-linux-gnueabihf-as -a=hogehoge.lst -o hogehoge.o hogehoge.s
arm-linux-gnueabihf-ld -o hogehoge hogehoge.s
アセンブラソースの出力はこんな感じ
aarch64-linux-gnu-gcc -S -o hogehoge.s hogehoge.c
aarch64-linux-gnu-as -a=hogehoge.lst -o hogehoge.o hogehoge.s
aarch64-linux-gnu-gcc -o hogehoge hogehoge.o
arm-linux-gnueabihf-gcc -S -o hogehoge.s hogehoge.c
arm-linux-gnueabihf-as -a=hogehoge.lst -o hogehoge.o hogehoge.s
arm-linux-gnueabihf-gcc -o hogehoge hogehoge.o
できたバイナリは普通に実行できる
./hogehoge
バイナリがどのアーキテクチャかはfileコマンドで確認できる
file hogehoge
17:デフォルトの名無しさん
17/04/15 04:44:00.98 2Mj3RTtW.net
32bitのARMでUbuntuのgnueabihfではデフォルトでThumb-2でコンパイルされる
ARM命令でコンパイルする場合はオプションを追加する
ARM命令の場合の例
-marm -march=armv7-a -mfloat-abi=hard -mfpu=vfpv3-d16
-marm -march=armv7-a -mfloat-abi=hard -mfpu=neon -ffast-math
実行例)
arm-linux-gnueabihf-gcc -O2 -marm -march=armv7-a -mfloat-abi=hard -mfpu=vfpv3-d16 -o hogehoge hogehoge.c
arm-linux-gnueabihf-gcc -O2 -S -marm -march=armv7-a -mfloat-abi=hard -mfpu=vfpv3-d16 -o hogehoge.s hogehoge.c
arm-linux-gnueabihf-as -a=hogehoge.lst -o hogehoge.o hogehoge.s
arm-linux-gnueabihf-gcc -marm -march=armv7-a -mfloat-abi=hard -mfpu=vfpv3-d16 -o hogehoge hogehoge.o
参考)
Thumb-2命令の場合の例
-mthumb -march=armv7-a -mfloat-abi=hard -mfpu=vfpv3-d16
-mthumb -march=armv7-a -mfloat-abi=hard -mfpu=neon -ffast-math
18:デフォルトの名無しさん
17/04/15 04:47:16.32 2Mj3RTtW.net
32bitARMアセンブラの参考URL
URLリンク(www.mztn.org)
64bitbitARMアセンブラの参考URL
URLリンク(www.mztn.org)
19:デフォルトの名無しさん
17/04/15 07:38:04.38 2Mj3RTtW.net
>>18の32bitARMのアセンブラのサイトの
URLリンク(www.mztn.org)
1: ldrb r3, [r0, #+1]! @ r3=mem[r0++]
strb r3, [r1, #+1]! @ mem[r1++]=r3
でエラーが出ます
ここは
1: ldrb r3, [r0], #+1 @ r3=mem[r0++]
strb r3, [r1], #+1 @ mem[r1++]=r3
ですね
20:デフォルトの名無しさん
17/04/15 08:02:58.82 2Mj3RTtW.net
補足
32bitARMでのシステムコールの呼び出しはEABIの方式で行ってください
.text
.align 2
.global _start
_start:
adr r1, msg @ address
mov r0, #1 @ stdout
mov r2, #13 @ length
mov r7, #4 @ sys_write
swi 0
mov r0, #0
mov r7, #1 @ sys_exit
swi 0
.align 2
msg:
.asciz "hello, world\n"
21:デフォルトの名無しさん
17/04/15 08:35:58.99 2Mj3RTtW.net
32bitARMでFPU命令を使う場合の例
arm-linux-gnueabihf-as -mfpu=vfpv2 -a=hogehoge.lst -o hogehoge.o hogehoge.s
arm-linux-gnueabihf-as -mfpu=vfpv3-d16 -a=hogehoge.lst -o hogehoge.o hogehoge.s
22:デフォルトの名無しさん
17/05/07 22:56:59.24 8v4hzv7f.net
Intel AVX512とか32ビットモードや16ビットモードでマシン語記述できるの?
16ビットモード(MS-DOS6.2)で32ビット命令を実行できることは確認ずみ。
23:デフォルトの名無しさん
17/05/08 01:10:33.28 UxHus5NQ.net
どうやってマシン語生成するつもりか分からんが、マシン語は記述できるだろ。
24:デフォルトの名無しさん
17/05/08 01:56:11.92 +dlahwH0.net
>>22
REXプリフィックスは別の命令の再定義なので
25:デフォルトの名無しさん
17/05/09 04:41:32.11 CfLPAbNS.net
いまじゃ解析とか簡単になっとるからなぁ
小学生でもできるんじゃない?
26:デフォルトの名無しさん
17/05/11 21:51:54.08 +ulrHAZU.net
ねえねえ、Altivecって知ってる?
27:デフォルトの名無しさん
17/05/13 00:24:52.24 YNo+ODse.net
それ作ったチームはインテルでAVX512に関わったんだっけ
28:デフォルトの名無しさん
17/07/19 15:57:14.47 4WYjcaP8.net
>>22
理屈の上ではアセンブラがそれらの命令をサポートしてれば可能。
ただ、今はアセンブラの方がMS-DOSサポートして無いだろうからクロス開発になりそう。
(動けば運が良かったって程度)
でもリアルモードでバイト数大きい64bit命令使うメリットは無い希ガス。
せめてプロテクトモードに移行してから64bit命令使った方が。。。
と言うか、Linuxのブートローダーからロングモード移行までの記事最近読んだけど、アセンブラから見たら多分16bit32bitじゃ無くてリアルモードかプロテクトモードかのが重要(使えるメモリの大きさが違う)な希ガス。
URLリンク(postd.cc)
29:デフォルトの名無しさん
17/10/19 07:34:02.07 5IzztSYd.net
TLCS-900H2のDL命令の意味を教えてください
ソースを見る限りではCALLと同等のようですが
30:デフォルトの名無しさん
17/12/20 04:38:28.77 y3D7Mbgz.net
LibreOfficeのExcel互換アプリ calc では既にPythonでマクロが書ける
31:デフォルトの名無しさん
17/12/20 04:39:01.17 y3D7Mbgz.net
誤爆した。スマン
32:デフォルトの名無しさん
17/12/22 18:09:17.57 bOdX3AhV.net
excel最近使ってないわ
33:デフォルトの名無しさん
18/02/21 13:16:23.71 VklNYIB8.net
初心者質問じゃないのだが、調べてもわからないので知ってる人がいたら教えて欲しい
Zynqを使ってハードウェアエミュレータを作ろうとしているんだが、
そのままだとアドレス0x40000000からしか自由に使えなくて困ってるんだけども、
Cortex-A9のMMUを設定するにはどうしたらいいんだろうか?
やりたいことはアドレス0x40000000から0x4FFFFFFFまでを0x00000000から0x0FFFFFFFにマッピングしたい
34:デフォルトの名無しさん
18/02/22 03:37:57.63 hXyx6D5H.net
>>33
MMUについてどれだけ知っているのか分からないが
とりあえずLinuxのARMv7周りのコードを調べるのがよいと思われ
"linux arm source mmu"辺りをググッてみるとか
あとはARMのリファレンスマニュアル
URLリンク(infocenter.arm.com)
から、「ARM アーキテクチャ」→「Reference Manuals」→「ARM アーキテクチャ リファレンス マニュアル ARMv7-A および ARMv7-R エディション」
のPDF、1267ページ以降を参照
大まかな手順としては
・ページテーブルを構築
・変換テーブルベースレジスタ(TTBR0、TTBR1)をセット
・変換テーブルベース制御レジスタ(TTBCR)をセット
・システム制御レジスタ(CP15 c1、SCTLR)レジスタのMMU有効化ビットをON
となると思われ
35:デフォルトの名無しさん
18/02/23 00:45:14.45 ulmXMJQn.net
>>34
ありがとう
linuxカーネルを参考にしてやってみる
36:デフォルトの名無しさん
18/02/24 13:07:22.87 tiS2olHY.net
>>34
armのドキュメント読みつつzynqでステップ実行しながらメモリの状態見てみたんだが、
以下の認識で合ってるだろうか?
・ページテーブルを構築
適当なメモリ領域にページテーブルを構築(要16kiBアラインメント)
(レジスタをいじって設定とかではなく例えば0x80000000番地に作っておく等)
・変換テーブルベースレジスタ(TTBR0、TTBR1)をセット
TTBR0はユーザー用、TTBR1はOS用
さっき用意したページテーブルの先頭アドレス(上位ビット)を渡す
下位ビットの方にその他の設定する
・システム制御レジスタ(CP15 c1、SCTLR)レジスタのMMU有効化ビットをON
SCTLRのBit0に1をセット
37:デフォルトの名無しさん
18/02/24 18:39:17.01 B8xdCHC7.net
>>36
俺はARMはちゃんと触ってないので確実なことは言えないが
基本的にはそれで合っていると思う
ページテーブルとTTBRは物理アドレス(PA)で管理、ページテーブル内は仮想アドレス(VA)とPAの対応関係にアクセス保護ビット等
ページテーブルが2段以上(ページディレクトリ経由)になる場合はページディレクトリ内のデータの解釈が少し変わる
RISC系CPUはTLBミスヒットした時のテーブルウォークを自前で叩いてやらないといけない場合があったが、ARMv7ではCPUが自動でやる模様
あと微妙にキャッシュの管理とMMU周りの管理が絡み合っているようで、ここを俺は把握し切れていない
とにかく、Cortex-Aではコプロセッサ#15(CP15)がMMUなので、CP15の制御レジスタ周りをよく見ておいたほうがよいと思われ
38:デフォルトの名無しさん
18/02/25 15:07:04.60 EC94jTzS.net
>>37
0x40000000の内容に0x00000000からアクセスできるようになった!
GBA(ARM7TDMI)のBIOSもちゃんと実行できてるっぽい
VRAM領域にアクセスしに行って止まってるが(;・∀・)
TLBのattributeの設定はとりあえず適当だが動いてるしよくわからんけど放置しよう・・・
39:デフォルトの名無しさん
18/02/25 18:36:29.28 zm40u4G6.net
>>38
おめでとう!
40:デフォルトの名無しさん
18/02/26 06:57:20.16 SxohJEGp.net
気楽にx86_64のアセンブラをやりたい人はこれを読むといいかもね
ただ、あまり詳しくは書かれてない
あくまで、初心者がx86_64アセンブラのとっかかりを掴むために読む本
CPUについての詳しい解説はあまり書かれてない(レジスタの解説程度)
x86_64のWindowsアセンブラ特有のスタックの使い方についても簡単に解説されてる
(x86_64のWindowsのアセンブラではスタック操作を自由にやってはいけない)
この本を読むとx86_64のアセンブラを簡単に試せるようになる
64ビットアセンブラ入門―64ビットCPUの基本構造もやさしく解説
URLリンク(www.amazon.co.jp)
41:デフォルトの名無しさん
18/02/26 15:57:09.08 SxohJEGp.net
x86_64のWindowsのアセンブラで最初に嵌るのがスタック関係
URLリンク(herumi.in.coocan.jp)
Windowsでのスタック
スタックは常に16byteアラインメントされています.
ただし関数呼び出し直後は戻りアドレス(8byte)がpushされているため, 8(mod 16)となっています.
関数内から別の関数を呼び出すときはアライメントを揃える必要があり,
引数4個のスタック分(32byte)を呼び出し元で確保する必要があります.
確保された領域は呼び出された側で自由に使えます.
Windowsでのスタックの扱い方はここのページを参照するといいかも
URLリンク(www.officedaytime.com)
x64アセンブラ関数の書き方の注意【すごく要注意】
スタックが自由に使えない
32ビットまでのインラインアセンブラでは好き勝手にpush/popしたりして使えていたスタックが
x64では厳しい使用制限を受けることになりました。
具体的には以下のような制限です。
スタックポインタが動くような操作をしていいのは関数の最初と最後の部分だけ
(フレームポインタ(後述)を設定しない場合)。
その部分は「prolog」「epilog」と呼ばれ、やっていいことが決まっている。
prologが終わった時点でスタックポインタは16の倍数になっていなければならない
(中から他の関数を呼ばない場合はこの制限はない)。
ただし、push/popやその他の方法でRSPを動かさない、
何も呼び出さない、
壊してはいけないレジスタをセーブ(push/popに限らずいかなる方法でも)しない、
例外処理をしない、
のすべての条件を満たす関数は「leaf」(関数呼び出しツリーの枝の末端の葉っぱ、くらいの意味でしょうか)と呼ばれ、
この制限を受けません。
前ページのコーディング例にprolog/epilogがないのはそのためです。
-------以下、prolog/epilogの方法はページを参照-------
42:デフォルトの名無しさん
18/02/28 14:26:24.02 S610+cRR.net
アライメントとアラインメントとか
用語もちゃんと揃えて欲しいな
43:デフォルトの名無しさん
18/03/08 20:28:48.99 uhDvi+9f.net
linuxでのx86_64のコンパイル&アセンブル
コンパイル
gcc -O2 -o hogehoge hogehoge.c
コンパイルでアセンブル出力&アセンブル&リンク
gcc -O2 -S -masm=intel -o hogehoge.s hogehoge.c
as -a=hogehoge.lst -o hogehoge.o hogehoge.s
gcc -o hogehoge hogehoge.o
注:gccに-Sオプションを付けた場合に-masm=intelオプションを付けるとInteニーモニックのアセンブルリストが出力される
(デフォルトではAT&Tニーモニックで出力される)
アセンブル&リンク
as -a=hogehoge.lst -o hogehoge.o hogehoge.s
ld -o hogehoge hogehoge.o
注:アセンブラソースに.intel_syntax noprefixを記述するとgasでIntelニーモニックを使えるようになる
(デフォルトではAT&Tニーモニック)
44:デフォルトの名無しさん
18/03/08 20:29:33.06 uhDvi+9f.net
例) Linuxアセンブラ版hello world
.intel_syntax noprefix
.text
.global _start
.align 4
_start:
mov rax, 1 # sys_write (1)
mov rdi, 1 # stdout (1)
movabs rsi, offset flat: msg # address(offsetを付けることによってアドレスをロードする)
# gasでは64bitイミディエイトや64bit絶対アドレス指定でのメモリからのロードを使う場合はmovabsを使う
mov rdx, offset flat: len # length(offsetを付けることによってアドレスをロードする)
syscall
mov rax, 60 # exit (60)
xor rdi, rdi # return 0
syscall
.data
.align 8
msg:
.asciz "hello, world\n"
.equ len, . - msg
.end
45:デフォルトの名無しさん
18/03/08 20:32:10.43 uhDvi+9f.net
64bitLinuxでの32bit x86のコンパイル&アセンブル
コンパイル
gcc -O2 -m32 -o hogehoge hogehoge.c
コンパイルでアセンブル出力&アセンブル&リンク
gcc -O2 -S -m32 -masm=intel -o hogehoge.s hogehoge.c
as -a=hogehoge.lst --32 -o hogehoge.o hogehoge.s
gcc -m32 -o hogehoge hogehoge.o
アセンブル&リンク
as -a=hogehoge.lst --32 -o hogehoge.o hogehoge.s
ld -melf_i386 -o hogehoge hogehoge.o
46:デフォルトの名無しさん
18/03/08 20:34:16.87 uhDvi+9f.net
例) Linuxアセンブラ版hello world(32bit)
.intel_syntax noprefix
.text
.global _start
.align 4
_start:
mov eax, 4 # sys_write (4)
mov ebx, 1 # stdout (1)
mov ecx, offset msg # address(offsetを付けることによってアドレスをロードする)
mov edx, offset len # length(offsetを付けることによってアドレスをロードする)
int 0x80
mov eax, 1 # exit (1)
xor ebx, ebx # return 0
int 0x80
.data
.align 4
msg:
.asciz "hello, world\n"
.equ len, . - msg
.end
47:デフォルトの名無しさん
18/03/10 06:44:54.80 L0iyZELB.net
あせんぶりゃー
あせんぶり
あせんぶる
48:デフォルトの名無しさん
18/03/11 17:22:40.99 lDE3fY11.net
x86_64のリファレンスマニュアル
インテルR エクステンデッド・メモリー 64 テクノロジー・ソフトウェア・デベロッパーズ・ガイド、第 1 巻
URLリンク(www.intel.co.jp)
インテルR エクステンデッド・メモリー 64 テクノロジー・ソフトウェア・デベロッパーズ・ガイド、第 2 巻
URLリンク(www.intel.co.jp)
49:デフォルトの名無しさん
18/05/03 11:01:18.80 0pg5Dj/G.net
8086にワード幅の相対ジャンプあるのに今頃気付いた…\(^O^)/…
orz
50:デフォルトの名無しさん
18/05/03 11:36:54.78 83GzP0HZ.net
86には無くない?
386以降だった気がする
51:デフォルトの名無しさん
18/05/03 11:38:07.04 83GzP0HZ.net
違った
相対ジャンプは、ほぼ全てが相対ジャンプだから、86からあるな
386からは、8bit限定じゃなくなったのは、条件ジャンブだ
52:デフォルトの名無しさん
18/05/03 12:21:57.39 0pg5Dj/G.net
うんまあそういう感じで多分勘違いしていた
というかワード幅のは絶対ジャンプといつのまにか思ってたらしい...(*ノノ)
53:デフォルトの名無しさん
18/05/03 13:31:52.82 bkPu29QU.net
Hugeモデルω
54:デフォルトの名無しさん
18/05/23 19:33:19.00 Au5e7VGg.net
僕の知り合いの知り合いができたパソコン一台でお金持ちになれるやり方
役に立つかもしれません
グーグルで検索するといいかも『ネットで稼ぐ方法 モニアレフヌノ』
Z4DKB
55:デフォルトの名無しさん
18/05/23 19:44:16.48 q+YDJHjh.net
正規化HUGEとタイリングHUGE
56:デフォルトの名無しさん
18/05/24 10:55:44.30 cPlRxlDn.net
.
57:デフォルトの名無しさん
18/06/13 15:38:35.51 lSIEjw1a.net
その昔条件分岐のオフセットが8ビットを超えると勝手にnear分岐に展開してくれるアセンブラがあってだな
58:デフォルトの名無しさん
18/06/13 15:56:44.91 mbrmHeFX.net
で?
59:デフォルトの名無しさん
18/06/13 17:23:26.62 5n7sRExk.net
edas86覚えてる人いる?
60:デフォルトの名無しさん
18/07/04 22:19:45.76 gFgZc5FG.net
TDC
61:デフォルトの名無しさん
18/07/05 16:39:14.28 AeL6VB/V.net
TDC
62:デフォルトの名無しさん
18/07/21 07:03:04.58 HztBSU4B.net
オブジェクト指向のアセンブラアプリのお薦めを教えてください。
63:デフォルトの名無しさん
18/07/21 10:03:59.76 JzufiDOi.net
Julia
64:デフォルトの名無しさん
18/07/31 18:07:47.27 K5ZjI7P1.net
初心者なので意味が解らないんだけど、オブジェクト指向って考え方なんじゃないの?
65:デフォルトの名無しさん
18/07/31 23:36:25.25 M9aZq/V8.net
ところで、2つの32BIT レジスタの値を、64BITレジスタの上位32bit、下位32bit に
分けて入れる場合、shld を使えばいいのかな?
32BIT 時代の場合は、ebx <--- dx:ax としたい場合、
mov bx,dx
shl ebx,16
mov bx,ax
などとしたもんだけど、64BIT モードで、rbx <--- edx:eax としたい場合、
例えば、
shld rdx,rax,32
mov rbx,rbx
とするのかな。
66:デフォルトの名無しさん
18/07/31 23:38:20.35 M9aZq/V8.net
あ、訂正させて。
多分、正しくは:
shl rax,32
shld rdx,rax,32
mov rbx,rbx
67:デフォルトの名無しさん
18/07/31 23:39:52.06 M9aZq/V8.net
もしかして、mmx レジスタや xmm レジスタの、shuffle 命令なども使えたりする
のだろうか??
68:デフォルトの名無しさん
18/07/31 23:44:49.05 M9aZq/V8.net
すまん。最訂正。
shl rax,32
shld rdx,rax,32
mov rbx,rdx
69:デフォルトの名無しさん
18/07/31 23:51:35.80 PrQlt9wc.net
>>68
もちつけ
70:デフォルトの名無しさん
18/07/31 23:53:48.39 Yh1Yhi2x.net
shl rdx, 16
mov ebx, eax
or rbx, rdx
71:デフォルトの名無しさん
18/07/31 23:55:11.65 Yh1Yhi2x.net
16じゃなくて32
72:デフォルトの名無しさん
18/07/31 23:58:34.01 M9aZq/V8.net
なるほど、つまり:
shl rdx, 32
mov ebx, eax
or rbx, rdx
と。OR を使うとは全く思いつかなかった。
73:デフォルトの名無しさん
18/08/01 00:00:05.11 M1fpQAcB.net
考えてみれば、C言語ではいつも、シフトとOR使ってやってた・・・。
74:デフォルトの名無しさん
18/08/01 00:02:01.85 s+zy6Um6.net
もちつけ
75:デフォルトの名無しさん
18/08/01 00:17:55.42 M1fpQAcB.net
【まとめ】
64BIT モードでは、mov 命令などの destination が、32BITレジスタの場合、
原則的に、対応する64BITレジスタの上位32BITがゼロクリアされてしまうの
で注意が必要。蛇足だが、destinationが16BITレジスタや8BITレジスタの
場合は、対応する64BITレジスタの残りの上位ビットは完全に保持される。
この結果、2つの同じビット数のレジスタを2倍のビット数のレジスタの上位、下位
に代入したい場合、
32BIT Legacy Mode で、ebx <--- dx:ax としたい場合、
mov bx,dx
shl ebx,16
mov bx,ax ;ebx(64BITモードだと、rbx) の上位16ビット(上位48BIT)は、
;直前のまま変化しない。
で良かったが、
64BIT モードで、rbx <--- edx:eax としたい場合、
shl rdx, 32 ; 左シフトの結果、rdx の下位32BIT は、0になる。
mov ebx, eax ; rbx の上位32BIT は(勝手に)0クリアされる。
or rbx, rdx
や、
shl rax,32 ; 左シフトの結果、rax の上位32BITに元の eaxが入る事になる。
shld rdx,rax,32 ; rdx : rax をひとまとめにして 32BIT分、左シフト。
mov rbx,rdx
などとする必要がある。
76:デフォルトの名無しさん
18/08/01 00:48:03.95 hfBYO5dB.net
64bitレジスタの上位が0になるのは無駄な依存関係を無くすため
32bitレジスタの部分書き換えは大きなペナルティが発生するので注意
77:デフォルトの名無しさん
18/08/01 00:52:48.93 hfBYO5dB.net
アセンブラで高速なコードを書くなら
インテルの最適化マニュアルを一通り読むことを勧める
IACAも非常に便利
78:デフォルトの名無しさん
18/08/01 20:01:51.01 UPXl5ngF.net
アセンブラは普通に書いただけでもCに比べてバイナリも非常に小さいし高速に動いてくれるよね
79:デフォルトの名無しさん
18/08/01 23:09:30.00 iFKJPY0w.net
ペナルティを避けるため、普通は同じレジスタでも別のでもいいから、movzx使って上位ビットが0だって明示してから使うべき
80:デフォルトの名無しさん
18/08/01 23:17:32.46 iFKJPY0w.net
今回の64ビットバージョンのrbx <--- edx:eax としたい場合は関係なかったけど、
mov bx,dxをやった後にebxやrbxを参照するとペナルティが発生するのは32ビットでも一緒だけどね
81:デフォルトの名無しさん
18/08/02 20:11:37.64 Hff70ZxX.net
>>77
これですかね
URLリンク(herumi.in.coocan.jp)
82:デフォルトの名無しさん
18/08/02 20:19:01.70 1EegAYN5.net
それ
83:デフォルトの名無しさん
18/08/02 21:46:38.87 Hff70ZxX.net
IACAってなんかすごい
84:デフォルトの名無しさん
18/08/02 23:06:24.79 vIaAZbox.net
>>79
確か、64BIT モードだと、そもそも、movzx reg64,reg32 に相当する専用命令が
存在せず、その代わりに、単なる mov reg32,reg32 を使う想定になっているはず。
なぜなら、後者でも上位32BITが0になるから。
一方、movsx reg64,reg32 については、新しい新命令として、movsxd なる
ものが導入されている。なぜなら、movsx の第二オペランドは、32BIT時代
から、8BIT か、16BIT レジスタしか採りえないから。命令自体で
第二オペランドのビット数が固定されていて、第二オペランドが
8BIT と 16BIT で別々の opcode になっていて、0x66 prefix でデータサイズ
を変えた場合は、第一オペランドのサイズが変わるだけ、という仕様だった
から。つまり、64BITモードでも、第二オペランドのBIT数は、
opcode 自体で固定されてしまっているので、REX.W や 0x66 prefix では
第二オペランドのBIT数の変更はされない、というのが素直な解釈だったから。
85:デフォルトの名無しさん
18/08/11 19:53:27.03 Pi7uIeu1.net
[test3.asm]
.data
my_mojiretu db 'somothing', 0 ;1
.code
mov rax,offset my_mojiretu ;2
xor rbx,rbx
mov al,my_mojiretu[rbx] ;3
-------------------------------------------------------------------
2 は、大丈夫なのに、3 だと、以下のようなエラーになる。なぜ?
test3.obj に「絶対アドレス」の relocation 情報が入ることにはなるハズなんだけど。
J:\Develop\C\masm64_s\masm64>d:\ml64\bin\ml64.exe /Fl test3.asm /link /libpath:"
C:\Program Files (x86)\Windows Kits\8.0\Lib\win8\um\x64" /subsystem:windows /def
aultlib:kernel32.lib /defaultlib:user32.lib /entry:main
Microsoft (R) Macro Assembler (x64) Version 9.00.30729.207
Copyright (C) Microsoft Corporation. All rights reserved.
Assembling: test3.asm
Microsoft (R) Incremental Linker Version 9.00.30729.207
Copyright (C) Microsoft Corporation. All rights reserved.
/OUT:test3.exe
test3.obj
"/libpath:C:\Program Files (x86)\Windows Kits\8.0\Lib\win8\um\x64"
/subsystem:windows
/defaultlib:kernel32.lib
/defaultlib:user32.lib
/entry:main
test3.obj : error LNK2017: 'ADDR32' relocation to 'my_title' invalid without /LA
RGEADDRESSAWARE:NO
LINK : fatal error LNK1165: link failed because of fixup errors
86:デフォルトの名無しさん
18/08/11 19:55:58.66 Pi7uIeu1.net
エラーでは、my_title になってるけど、5ch に登校する際に、
ソースを my_mojiretu に変えただけなので、同じと思って。
あと、somothing は、something の typo。
87:デフォルトの名無しさん
18/08/11 20:05:28.32 Pi7uIeu1.net
あー。例外的に2の部分の、
mov reg,imm
は、imm に 64BIT 即値が入れられるけど、3の部分では、
ModRMの間接参照の
[ebx + disp]
を使ってるけど、この形では、dispに32BIT までしか入れられないからだな。。。
なるほど。つまり、
mov al,my_mojioretu[ebx]
は、
mov al,[ebx + disp64]
としたくても、AMD64 ではそのようなメモリオペランドが使えないので、
mov al,[ebx + disp32]
にしかアセンブルできないと。
だから、絶対アドレスが、32BIT を超えるような値になった場合にはどうしようも
ないと。
88:デフォルトの名無しさん
18/08/11 20:08:54.58 XlVyBwpc.net
ちょっと勉強になった
64bitでasm触ることなくなったもんなー
89:デフォルトの名無しさん
18/08/11 22:13:23.67 QecvtyFY.net
>>85
実際に試してないから推測だけど、2では64bitレジスタに代入しているのに対して
3では8bitレジスタALに代入しようとしている。EAXかRAXに代入してみれば動くんではないかと。
90:デフォルトの名無しさん
18/08/12 06:39:04.85 kb51JNcZ.net
>>89
関係ないと思うよ。
よく読んでみて。
91:デフォルトの名無しさん
18/08/12 06:49:59.09 kb51JNcZ.net
AMD64 では、ModRM を使った MemoryOperand の [reg64 + disp] のような形式の場合、
disp の BIT 数が、最大でも、
[reg64 + disp32]
のように 32BIT までが限界で、64BIT の disp64 は存在していない。
imm も「一般的には」、imm32 までで、imm64 は使えない。
ところが、mov reg,imm に関しては、例外的に
mov reg64, imm64
という命令が存在している。また、似た話として、
ModRM を使わない MemoryOperand では、disp64 のようなものが例外的に
存在していて、
mov reg,[disp64]
というものが存在している。ただし、意味的には、[disp64] ではなく、[moffset64]
のような意味合いで、
mov reg,[moffset64] や
mov reg,moffset64
と書かれることがある。この場合、[] が付いてなくても意味は同じ(混乱注意)。
ちなみに、mem64 は、データサイズが 64BIT という意味なので、
qword ptr [xxxx]
の意味になるので、また違う。
つまり、レジスタに入れてアクセスできるアドレスは64BITなのに、固定アドレスを入れてアクセス
できるメモリは、32BIT に制限されやすい、ということ。ただし、上記のような例外が用意されている
ので、絶対に32BITを超えた固定アドレスのメモリをアクセスできないというわけではない。
92:デフォルトの名無しさん
18/08/12 06:59:38.95 kb51JNcZ.net
ちなみに、
.data
ラベル名 db 'xxxx',0 ;1
.code
lea ebx,ラベル名 ;2
のような場合、一見、2の第二オペランドは、ModRM に encode されるので、
lea ebx,[disp32]
になってしまうから、この場合も、32BIT の限界に遭遇してしまうのではないかと
思ってしまうかもしれない。ところが、実際には、
lea ebx,[rip + rel_addr32]
のように命令ポインタの rip 相対のアドレスとして、encode されるので、また、事情が
違ってくる。結論的には、この場合は、ラベル名がリンクに指定した obj の中にある
限りにおいては、32BIT の限界を特に気にすることは無い。
93:デフォルトの名無しさん
18/08/12 07:04:02.85 kb51JNcZ.net
>>92
間違った。 ebx ではなく、rbx だった:
lea rbx,ラベル名 ;2
lea rbx,[disp32]
lea rbx,[rip + rel_addr32]
94:デフォルトの名無しさん
18/08/16 12:39:22.96 ZqqdGQwm.net
>>41
実は、以下のようにしておくだけで、SEH例外のサポートも含めて、
ほぼ、push, pop は自由に出来るようになるらしい。
1. 関数の最初と最後を以下のように書く :
push rbp
mov rbp, rsp
・・・
pop rbp
ret
2. rbp を frame pointer に使っているということを、関数の prolog に書く。
【「ほぼ」 の例外】
call 関数名などの関数コールの直前では、rsp を16バイトアラインしてある
必要があること。それさえ気をつけていれば、push, pop は自由に行える。
【16倍とスタックアラインについて】
push rbp のおかげで、return address の 8 バイトと合わせて、直後からは、
上手く勝手に rsp が 16 バイトにアラインされた状態になってくれる。
だから、余り難しい事を考える必要は無い。
95:デフォルトの名無しさん
18/08/16 13:12:50.69 ZqqdGQwm.net
frame pointer(rbp) を使わない場合は、関数の通常部分では、rsp を最初から最後まで
固定しなくては、構造化例外を処理出来なくなる。
なので、rsp が変化する事になる push, pop が使えなくなる。
(なお、人間にとっては便利でも、コンパイラにとっては、元々 push, pop は使いにくい
命令であった。)
x86、x64 アーキテクチャでは、mov reg, reg/mem のような事は出来ても、
mov mem, mem は出来ない。ところが、この、push, pop についてはそれが
出来てしまう数少ない例外。
例えば、
push qword ptr [ebp + disp1] ;1
や
push qword ptr [esp + disp1] ;2
で、ローカルの auto 変数をスタックに保存する事が出来る。ところが、
mov qwrod ptr [esp + disp1], qword ptr [esp + disp2] ;3
とは出来ない。だから、push 命令を使うと、実はパフォーマンスが向上する可能性も
秘めてはいるかも知れない。ただし、これも、レジスタの個数が十分沢山ある
近年では、必ずしもそうとも言えないかもしれない。レジスタの個数が不足して
スタックに保存したくなった場合、
mov [esp + disp1], reg ;4
と書けばいいわけであって、3 のように書く必要性は、近年では下がっているようだから。
96:デフォルトの名無しさん
18/08/16 13:27:50.54 ZqqdGQwm.net
>>95
誤:esp, ebp
正:rsp, rbp
【なぜ、3の必要性が少ないかについて】
3のようにしなくても、そもそも、3の第二オペランドの値は、メモリ上において
あるのだから、レジスタが不足しても値が消えてしまう事はない。だから、
保存の必要も無い。
レジスタが不足した場合に保存する必要があるのは、必ずレジスタの値。
だから、mov [rsp + disp], reg の形式で十分保存できてしまう。
97:デフォルトの名無しさん
18/08/16 15:37:56.45 y9SUHRBN.net
>>96
間違えてやんの
だせー!
98:デフォルトの名無しさん
18/08/16 21:00:56.95 aOzS/OcU.net
内部的にロード、ストアは別命令
アセンブラの命令数とかあまり関係ない
99:デフォルトの名無しさん
18/08/18 06:32:40.93 v9RxAPQU.net
>>92
コードセグメントのリテラルならrip相対でエンコードされると思うけど、データセグメントでそれ可能だったっけ?
最近アセンブリ言語いじってないから確認してないけど、それが可能だったら>>85の3はエラーにならないのでは。
>>95
最適化マニュアルのスループットとレイテンシの表見れば書いてあるけど、
push、popはロードユニットやストアユニットだけじゃなくALUも使う。その分無駄。
100:デフォルトの名無しさん
18/08/18 06:35:45.68 v9RxAPQU.net
push、popはコードサイズに制限のある、プロローグ、エピローグ部分で使うことはあるけど、
あまり必要性はなくなったよ。
101:デフォルトの名無しさん
18/08/18 07:05:31.99 v9RxAPQU.net
push、popみたいに複数のμOPになる命令は利用可能なデコーダーも制限されるので
他の命令のデコードも阻害しやすい。
演算命令のメモリオペランドみたいに、フュージョンされて簡単デコーダーで発行できるようになったのもあるけど。
102:デフォルトの名無しさん
18/08/18 08:53:46.48 LWSvYoUk.net
>>99
>コードセグメントのリテラルならrip相対でエンコードされると思うけど、
>データセグメントでそれ可能だったっけ?
可能。
103:デフォルトの名無しさん
18/08/18 09:10:13.08 LWSvYoUk.net
>>99
>最近アセンブリ言語いじってないから確認してないけど、それが可能だったら>>85の3はエラーにならないのでは。
エラーメッセージをよく読むと書いてあるけど、linker に、
/LA RGEADDRESSAWARE:NO
というオプションを渡すと、エラーが消える。
これは、[rbp+disp] の disp には、32BIT までしか入れられないので敢えて
エラーを出しているだけなので、本当は特に問題にはならない。
104:デフォルトの名無しさん
18/08/18 14:23:17.32 LlnBri0A.net
>>103
それ、可能と言えば可能だけど、64bit化のメリットのかなりの部分が消えてしまうし、
DLLでも制限なく使えるんだっけ?
と思って調べたらやっぱ問題あるよなあ。
URLリンク(www.webtech.co.jp)
105:デフォルトの名無しさん
18/08/18 19:54:44.26 D84MOd5V.net
>>103
mov cl, hogehoge
これでアセンブルして、dumpbin /relocations test01.obj
これで見ると
hogehogeがREL32になる(PC相対の32bitオフセット)
ラベルの種類としてRIP相対のREL32はあるけど
通常のレジスタに32bit相対のラベルの種類がないのでは?
だからエラーになると
106:デフォルトの名無しさん
18/08/18 21:13:26.29 D84MOd5V.net
簡単なWindowsのアプリを作ってWinMainのアドレスを表示すると
0x000000003fdf1770
俺の環境ではこんな値が出た
これってアドレスとしては1GBくらいの位置
下位32bitの絶対アドレスで指定すると符号付と解釈した場合に
残り1GBの範囲しかアクセスできない
だから、64bitのWindowsや/3GBスイッチを指定した32bitWindowsでは
下位32bitの絶対アドレスで指定するなとマイクロソフトは決めたのでは?
RIP相対なら開始アドレスに関係なくRIPの相対値なので
プログラムがロードされた位置に関わらず2GBまでアクセスできる
107:デフォルトの名無しさん
18/08/18 21:29:59.45 D84MOd5V.net
同じようなプログラムを32bitで作ってコンパイルしたらWinMainの開始アドレスは
0x013215a0
アドレスとしては19MBくらいの位置
64bitアプリは32bitアプリよりもずっと高位のアドレスにロードされるんだろうね
だから64bitアプリでは下位32bitでの絶対アドレス指定は禁止してるのかも
108:デフォルトの名無しさん
18/08/19 12:41:20.07 plhuPGbS.net
論理的に高位か下位かはどうでもよくね?
109:デフォルトの名無しさん
18/08/19 16:59:22.46 XvleiWNb.net
>>108
通常のプログラムが扱えるのは論理的なアドレスだからな
関係なくないよ
>>85の
mov al,my_mojiretu[rbx] ;3
のような下位32bitの絶対アドレスで指定する場合、扱えるデータの量が減る
上の例では0から2GBの範囲しかアクセスできないのに
論理アドレスで1GB付近からロードされたら扱えるスタティックに割り当てられたデータの量が極端に減ってしまう
110:デフォルトの名無しさん
18/08/19 17:05:58.03 XvleiWNb.net
だからこそ
>>85の
mov al,my_mojiretu[rbx] ;3
のようなコードを書くとリンカがエラーを吐くようになってるんだろうね
下位32bitの絶対アドレスで指定するなと
111:デフォルトの名無しさん
18/08/19 17:21:35.92 XvleiWNb.net
ほとんどのCPUでは64bitのアドレスを直接指定する方法は限定されてて、実行速度も遅くなる
だからWindowsやLinuxでは64bitでもデフォルトではスタティックに割り当てられたシンボルは
だいたい32bitの値として扱ってる
(Linuxではコンパイラのオプションでメモリモデルを指定できて
スタティックなシンボルを64bitの値として扱うこともできる)
64bit Windowsの場合、かなり高位のアドレスにロードされるようだから
RIP相対の32bitの値として扱ってるのだろう
ちなみにこれはスタティックに割り当てられたデータだけで動的に割り当てられたデータは
64bitのポインタ値で扱われるのでユーザプログラムが扱える全仮想メモリ領域に配置できる
112:デフォルトの名無しさん
18/08/19 17:30:58.64 XvleiWNb.net
64bitARMの場合、Linuxではスタティックなシンボル値読み込む場合
adrp x0, :pg_hi21:hogehoge
add x0, x0, :lo12:hogehoge
これで読み込む
これで33bitのページ単位でPC相対のアドレスを読み込める
つまり64bitのARMではスタティックなシンボル値は33bitのPC相対アドレスとして扱ってる
(相対なのはページ単位なので下位12bitは動かせない、下位12bitは絶対アドレス値を足してるので)
113:デフォルトの名無しさん
18/08/19 17:34:00.29 XvleiWNb.net
64bitのARMのadrp命令と同等の命令はRISC-Vや最近発表されたnanoMIPSなどでも採用されてる
RISC-VやnanoMIPSは33bitではなく32bitだが
114:デフォルトの名無しさん
18/08/19 17:41:09.62 XvleiWNb.net
スタティックなシンボル値の制約はアセンブラではなくあくまでコンパイラの仕様だが
(コンパイラ側でシンボルを扱う場合にあえて下位32bitしか読み込まない仕様にしてる)
最近のアセンブラプログラミングでは高級言語とリンクすることが多いので必須な知識
115:デフォルトの名無しさん
18/08/19 19:20:24.59 r48xSuow.net
>>111
> ちなみにこれはスタティックに割り当てられたデータだけで動的に割り当てられたデータは
> 64bitのポインタ値で扱われるのでユーザプログラムが扱える全仮想メモリ領域に配置できる
> ほとんどのCPUでは64bitのアドレスを直接指定する方法は限定されてて、実行速度も遅くなる
つまりこういうこと?
・動的に割り当てられたデータは64bitでアクセスできるけど実行速度が遅くなる
・静的に割り当てられたデータは32bitでアクセスするように制限されてるけど実行速度は速い。
・ただしLinuxの場合、メモリモデルを指定して再コンパイルすればこの制限はなくなる
116:デフォルトの名無しさん
18/08/19 20:02:42.41 XvleiWNb.net
>>115
>・動的に割り当てられたデータは64bitでアクセスできるけど実行速度が遅くなる
そもそも動的なデータは64bitのポインタで管理されるので最初から全アドレスにアクセスできる
>・静的に割り当てられたデータは32bitでアクセスするように制限されてるけど実行速度は速い。
違う、あくまでシンボルを32bitのアドレスとして読み込んでるだけでデータサイズは関係ない
x86_64でも64bitのアドレスを指定して読み込む命令は限られてるし、
実行速度の面でも効率が悪いのでRIP相対で32bit分だけを使ってる
たとえば、
mov rcx, data01
とした場合、data01の部分はRIP相対の32bitアドレスになる、読み込まれるデータは64bitの値
RISC CPUだとアドレスを読み込んでからデータに読み書きするという2段階になるので
たとえば、64bitのARMだと
adrp x0, :pg_hi21:data01
add x0, x0, :lo12:data01
ldr x0, [x0]
と下位33bitでPC相対アドレスとしてシンボルが読み込まれる
RISC-Vの絶対アドレスだと
lui a0, a0, data01
addi a0, a0, data01
ld a0, (a0)
PC相対だと
1: auipc a0, %pcrel_hi(data01)
addi a0, a0, %pcrel_lo(1b)
ld a0, (a0)
こうなる
(%pcrel_lo()では対応するpcrel_hi()のラベルを指定)
117:デフォルトの名無しさん
18/08/19 20:06:20.81 XvleiWNb.net
RISC-Vの絶対アドレスのところが間違ってた
不正解
lui a0, a0, data01
addi a0, a0, data01
ld a0, (a0)
正解
lui a0, %hi(data01)
addi a0, a0, %lo(data01)
ld a0, (a0)
118:デフォルトの名無しさん
18/08/20 06:10:04.15 yBkytAxc.net
>>116
アドレッシングの話をしているだと思ったのではしょったけどこう書けばいいですかね
・動的に割り当てられたデータは64bitアドレッシングでアクセスできるけど実行速度が遅くなる
・静的に割り当てられたデータは32bitアドレッシングでアクセスするように制限されてるけど実行速度は速い
・どちらの場合も読み書きできるデータサイズに制限はない
・ただしLinuxの場合、メモリモデルを指定して再コンパイルすればこの制限はなくなる
119:デフォルトの名無しさん
18/08/20 07:34:26.88 VWtXo5Rn.net
何で、動的に割り当てられた変数と静的に割り当てられた変数の
アクセス速度を比較するのか意味不明だが
一番アクセスが速いのはローカル変数だと思うぞ
ローカル変数はdisplacement付きのスタックポインタ間接アドレッシングでアクセスできるので
ほとんどのCPUでdisplacementが届く範囲なら1命令でロード、ストアができるからね
120:デフォルトの名無しさん
18/08/21 13:09:22.87 rmPseMne.net
>>119
今までの話の流れで言うと、速度を比較するのが目的ではなくて、
なぜ静的に割り当てられたデータは32bitアドレッシングでアクセスするように制限されているのか?
ですよ。普通に考えたら64bitアドレッシングが制限なくできて当たり前だろ。なんで?ってことです。
121:デフォルトの名無しさん
18/08/21 13:14:13.58 EQ4qcC3V.net
x86の64bitモードでのアドレッシングは全て64bit
122:デフォルトの名無しさん
18/08/21 16:35:27.52 R5Y2p11o.net
>>120
命令サイズを節約してるだけ
バラバラにコンパイルされた.oに対して後から命令長は変えられないんでデフォでそうなってる
変えたければラージモデルの類のコンパイルオプションがあるはず
123:デフォルトの名無しさん
18/08/21 19:52:55.59 JiPBZbts.net
>>120
64bitのデータだろうが32bitデータだろうがデータがキャッシュに入ってれば
キャッシュからデータを読み出す速度は変わらないが、
64bitアドレスを即値で指定すると
CISC CPUの場合、64bitアドレスの分、命令のオペランドの長さが長くなるので
今時の複数の命令を同時発行できるCPUだと一度に発行できる命令の数が減るので遅くなる
64bitのアドレスだけで8バイトにもなるからね
RISC CPUの場合は64bitのアドレスを一度に読み込めないので複数の命令に分けて読み込むが
64bitのアドレスを読み込むと命令数が増える
結局、静的データやジャンプ先のラベルはは32bitアドレスに限定したほうが結果的に速くなる
たいていのプログラムで静的データやジャンプ先のラベルで
32bitの範囲を超えるような応用プログラムは極一部の分野だけだしね
その極一部の応用プログラムのために性能を落とす必要はない
スパコンでも使われるLinuxではメモリモデルとして
静的データやジャンプ先のラベルを64bitで扱うようにコンパイルするオプションがある
このページはPGIのコンパイラのページだがわかりやすく説明してある
URLリンク(www.softek.co.jp)はこのページ
ARMやx86_64、POWERのgccでも-mcmodel=largeや-mcmodel=mediumがあったりする
(ARMでは-mcmodel=largeはあるが-mcmodel=mediumはない)
URLリンク(gcc.gnu.org)
URLリンク(gcc.gnu.org)
URLリンク(gcc.gnu.org)
124:デフォルトの名無しさん
18/08/22 02:39:05.86 J61dDDqI.net
>>104
確か、そのリンカオプションは、DLL作成時に指定するとエラーになる。
また、アプリの場合だと、relocation 情報が strip されて、EXE ファイルの中にはなくなっているのに対し、DLLだと relocation 情報が最後まで残されたままになっている。
>>105
あなたが使っている用語が x86 や x64 とは合わずめちゃくちゃなので何を聞いているのか分からないが、
hogehoge db 'xxxx', 0
mov cl, hogehoe 1
とすると、
mov cl,[offset hogehode]
と言う意味になり、encode としては、
mov cl, [RIP + (offset hogehode - offset label1)]
label1:
のように、RIP 相対の disp
mov cl, [RIP + disp32]
に encode される。この場合の disp32 は、意味としては、rel32 で、
RIP からの32BIT相対アドレス。
一方、似て非なるものとして、
mov cl, hogehode[rbx]
とすると、
mov cl, [offset hogehode + rbx]
即ち、
mov cl, [rbx + disp32]
と翻訳される。この場合の、disp32 は、32BIT絶対アドレス。 同じ、disp32 でも、意味は異なる。しかし、disp は、32BITまでで、 64BIT 値のものは存在していない。一方、64BITアドレスも一応は使えるように、
mov REG64, ADDR64 ; REG64 は、RAX, RBX, RCX, EDX, RBP, RSI, EDI など。
や
mov ACC, [ADDR64] ; ACC は、al, ax, eax, rax
という命令が、 専用命令として特別扱いとして存在しているが、特殊中の特殊。
125:デフォルトの名無しさん
18/08/22 02:48:04.81 J61dDDqI.net
>>124
訂正:
hogehoge db 'xxxx', 0
mov cl, hogehoge
とすると、
mov cl,[offset hogehoge]
と言う意味になり、encode としては、
mov cl, [RIP + (offset hogehoge - offset label1)]
label1:
のように、RIP 相対の disp
mov cl, [RIP + disp32]
に encode される。この場合の disp32 は、意味としては、rel32 で、
RIP からの32BIT相対アドレス。
ちなみに、masm では、
hoge1 db 'aaa' ;1
と
hoge2: db 'aaa' ;2
は明確に区別されており、hoge1 は、byte 型の配列変数のような取り扱いになり、
mov al, hoge1 ;1
は、masm には通らないが、旧来のアセンブラの感覚で言えば、意味的には、
mov al, qword [offset hoge1] ;3
となり、hoge2 の方は、直後の db 命令とは全く関係の無い単なる near アドレスと解釈され、
mov rax, hoge2 ;4
は、意味的には、
mov rax, offset hoge2 ;5
となる、ただし、4は、もしかするとそれ自体が文法上、masm の構文に合わないかもしれない。
masm は、「マクロアセンブラ」であって、通常のアセンブラとは結構異なるので。
126:デフォルトの名無しさん
18/08/22 02:50:10.88 J61dDDqI.net
>>125
誤: mov al, qword [offset hoge1] ;3
正: mov al, byte [offset hoge1] ;3
これも、masm 流には、
mov al, byte ptr [offset hoge1] ;3
nasm 流には、
mov.b al, [offset hoge1] ;3
みたいな感覚。みたいなだけで、実際にはそのまま書くと、エラーになる
かも知れない。
127:デフォルトの名無しさん
18/08/22 02:55:16.05 J61dDDqI.net
>>124
さらに補足すると、
mov cl, [rbx + disp32]
の disp32 は、rbx の中身によって意味が変わってきて、
1. disp = 32BIT 相対アドレス (rbx が絶対アドレスの場合)
2. disp = 32BIT 絶対アドレス (rbx が相対アドレスの場合)
となる。2. の例としては、
rbx = 配列添え字 * (配列の要素のバイト数)
のような場合。1. の例としては、
rbx = 構造体の先頭アドレス
のような場合。
128:デフォルトの名無しさん
18/08/22 04:37:08.89 8qwUBnhH.net
>>127
今やってみたが
64bitアプリを通常にコンパイルした場合のWinMainのアドレス
0x000000013f291770
/largeaddressaware:noを付けてコンパイルした場合のWinMainのアドレス
0x0000000001241770
/largeaddressaware:noを付けるとプログラムがロードされるアドレスが変わる
64bitのアプリを通常にコンパイルするとWinMainのアドレスが0x000000013f291770
およそ先頭から5GBの位置
つまり、32bit絶対アドレスでは届かない位置にプログラムがロードされてる
/largeaddressaware:noをつけると先頭から18MBくらいの位置
エラーが出るのは32bit絶対アドレスでは届かない位置にロードされる可能性があるからだろうな
129:デフォルトの名無しさん
18/08/22 04:40:24.11 8qwUBnhH.net
補足:
/largeaddressaware:noを付けると64bitアプリでもメモリは2GBまでしか使えなくなる
130:デフォルトの名無しさん
18/08/22 04:46:45.21 8qwUBnhH.net
つまり、>>128が示してることは
Windowsの64bitアプリでは
mov al,my_mojiretu[rbx]
のような書き方はしてはいけないということ
131:デフォルトの名無しさん
18/08/22 08:30:00.67 WDZbf6Te.net
>>124 XvleiWNbとは別人だよね?
/LARGEADDRESSAWARE:NOの辺りからなんか違和感あって、「そうなん?」って感じだったんだけど。
ARMやコンパイラの仕様だとかまで出てきて訳わからなくなるところだったよ。
>一方、似て非なるものとして、
> mov cl, hogehode[rbx]
>とすると、
> mov cl, [offset hogehode + rbx]
>即ち、
> mov cl, [rbx + disp32]
>と翻訳される。この場合の、disp32 は、32BIT絶対アドレス。 同じ、disp32 でも、意味は異なる。
>Windowsの64bitアプリでは
>mov al,my_mojiretu[rbx]
>のような書き方はしてはいけないということ
今までなんで絶対アドレスが出てくるのか疑問だったけど、コンパイラはこういうコードは吐かない、ってことだよね。
132:デフォルトの名無しさん
18/08/22 19:32:17.75 J61dDDqI.net
>>131
>>124 XvleiWNbとは別人だよね?
別人。ARMは使ったこと無い。
133:デフォルトの名無しさん
18/08/22 19:39:47.75 J61dDDqI.net
>>130
でも現実は、複雑。
なぜなら、COFFの仕様的には、obj ではない Image(EXEやDLLの事) のためだけに
ある .reloc section には、64BIT 絶対アドレスの再配置も行えるようになっているから。
現状の MS 製の link.exe がどうなっているかはともかく。
134:デフォルトの名無しさん
18/08/22 19:45:45.82 J61dDDqI.net
>>133
すまん。間違った。
mov al,my_mojiretu[rbx]
は、意味的には、
mov al, [rbx + offset my_mojiretu]
となって、最後は、
mov al, [rbx + disp32]
となるが、disp32 の部分は、disp64 の命令は存在していないので、
.reloc section が 64BIT 絶対アドレスに対応していても、無理だった。
勘違いした。
135:デフォルトの名無しさん
18/08/22 19:57:50.56 J61dDDqI.net
>>128
一応、論理的には、WinMain は、code (.text) section に置かれる。
my_mojiretu みたいなものは、.data section (など)に置かれる。
my_mojiretu みたいなものは、初期化(初期値)データなので、
2GB も使えれば十分ではあるはず。もし、2GB を超えるのなら、exe ファイルの
サイズも 2GB を超えるはず。
という事で、初期化データのおかれた section のアドレスが、2GB 未満
に置かれるならなんとかなるはず。
というか、通常、exe ファイルは、relocation 情報が strip されているので、
確か、Optional Header の BaseOfCode に配置したいアドレスを入れておける。
だから、その値を小さめにしておけば、初期化データのアドレスを 2GB 未満
の位置に配置する事はそんなに難しくないはず。
確か、32BIT 時代は、0x40000 位の値だった。
136:デフォルトの名無しさん
18/08/22 20:02:29.70 J61dDDqI.net
>>135
正しくは、BaseOfCode ではなく、ImageBase の方だった。
正しい値は、0x40000 ではなく、1桁大きい、0x400000 だった。
64BIT COFF では、変わってるかもしれない。確か、PREFERED_BASE
などという名前も記憶にある。
ImageBase Preferred address of first byte of image when loaded into memory;
must be a multiple of 64K. The default for DLLs is 0x10000000.
The default for Windows CE EXEs is 0x00010000.
The default for Windows NT, Windows 95, and Windows 98 is 0x00400000.
137:デフォルトの名無しさん
18/08/22 20:11:19.88 J61dDDqI.net
>>128
自分の勘だと、そのアドレスは、WinMain よりも、DLL の DllMain が置かれるような
値になってるね。
不思議だ。WinMain をそんな大きなアドレスに置く必要性は余り無いハズなので。
初期化データが 2GB 未満に置かれていても、malloc() や、new で確保されるデータは、
64BIT アドレスにできるはずだし。なお、
1_3f29_1770
↑は、32BIT を超えて、33BIT の値だな・・・。なんちゅう大きな値だろう。
138:デフォルトの名無しさん
18/08/22 20:46:10.32 dx23aElG.net
64bitもアドレス空間があるんだから
多少大きくても何の問題も無いだろ
139:デフォルトの名無しさん
18/08/22 21:22:24.95 WDZbf6Te.net
>>134
32bitのフラットメモリモデルだと、静的変数はイメージにはオフセットを入れといて、
実行時にローダで書き換えてたんだと思うんだけど、64bitでは絶対アドレスは制約が大きくなるから変だと思ったんだ。
絶対アドレスはコンパイラでも使えなくはないけど、デバイスドライバでメモリマップトI/O操作するような時しか使わないと思う。
64bitでイメージベースが大きくなったのは、セキュリティ関係でランダマイズしたりとか、
mov al,my_mojiretu[rbx]
みたいなコードが例外吐いて特定困難なバグが発生するのを防止してるのでは?
140:デフォルトの名無しさん
18/08/22 21:24:18.64 WDZbf6Te.net
例外吐くことで
141:デフォルトの名無しさん
18/08/23 05:44:12.90 sOVf8lyT.net
>>135
コマンドライン用の簡単なC言語の64bitのプログラムで試したが
main関数のアドレス=0x000000013f7f1000
data sectionで定義した変数data01のアドレス=0x000000013f7fc087
だったぞ
完全に32bit絶対アドレスの範囲を超えてる
142:デフォルトの名無しさん
18/08/23 07:08:50.83 sOVf8lyT.net
64bitのWindowsアプリを作って.data sectionの変数のアドレスも表示してみた
WinMain address = 0x000000013fd419a0
data sectionの変数のアドレス
data01 address = 0x000000013fd4d000
/largeaddressaware:noを付けた場合
WinMain address = 0x00000000013619a0
data sectionの変数のアドレス
data01 address = 0x000000000136d000
143:デフォルトの名無しさん
18/08/23 07:09:02.23 4LRopBJn.net
>>139
>64bitでイメージベースが大きくなったのは、セキュリティ関係でランダマイズしたりとか、
>mov al,my_mojiretu[rbx]
>みたいなコードが例外吐いて特定困難なバグが発生するのを防止してるのでは?
意味不明だ。別に、
mov al,my_mojiretu[rbx]
というコードが悪いわけではない。
むしろ、最適化のためには使った方が効率が良くなる。
144:デフォルトの名無しさん
18/08/23 07:22:22.74 4LRopBJn.net
>>141-142
もしそうだとすると、VC++ の吐くコードがx64の命令を上手く使いきれてないという事になる。
本来であれば、アドレスの配置を上手く行うだけで、64BIT モードでも特に問題なく
mov al,my_mojiretu[rbx]
という命令は使えて、かつ、64BIT アドレスの制限を受けるわけでもないのだから。
ちなみに、アプリの EXE は、リンク後は固定アドレスで、ローダーがアドレスを再配置
する事はない。だから、ImageBase を小さい値になるようにリンクしさえすれば、
問題が生じない。
145:デフォルトの名無しさん
18/08/23 07:27:31.64 4LRopBJn.net
>>139
>64bitでイメージベースが大きくなったのは、セキュリティ関係でランダマイズしたりとか、
通常、コンピュータソフト、特にOSのセキュリティーというのは、そういう人間的なもの
ではなくて、もっと厳密な物だ。
ランダマイズして撹乱して相手の目をくらます、などという方法は通常取られない。
実際、EXE ファイルを解析した経験からしても、ランダマイズなどは全く行われていない。
何回リンクしても、同じアセンブリソースや、同じC++ソースなら、全く同じアドレスになる。
異なるソースであっても、ベースアドレスなどは、ほとんどの場合、固定値。
146:デフォルトの名無しさん
18/08/23 07:58:52.05 4LRopBJn.net
>>138
実際には問題がある。なぜなら、そんなにアドレスが大きいと、さっきから話題の
mov al, my_mojiretu[rbx]
という命令が使えなくなるからだ。
これは、グローバルな配列変数を、添え字でアクセスするような場合に良いコードに
なる事がある。僅かではあるが。もし、この命令が使えないとなると、
mov rdx,offset my_mojiretu
mov al,[rdx + rbx]
のように、2つの命令を使わなくてはならなくなり、最適化上、不利になる。
147:デフォルトの名無しさん
18/08/23 08:10:29.27 wxGNRrqx.net
そんな事言い出したら
4GBや64KBに限定した方が小さいコードになるから
compactモデルにしよう
とかいう話にもなる
昔に戻りたい?
何のための64bit?
148:デフォルトの名無しさん
18/08/23 08:22:23.99 4LRopBJn.net
>>147
だから、そういうことじゃなく、EXEファイルの中に、2GBを越える初期化データを
誰が入れたいかって話なんだ。
別に、ImageBase を小さい値にしていても、malloc() や、new するデータは、
6GBでも理論上は確保できるわけで、制限されるのは、EXEファイルの中の
初期化データのサイズが2GBまで、ってだけなんだ。
それで、使えるマシン語の間接オペランドの種類が1つ増やせる。
mov 命令だけでなく、add, sub, mul, div, idiv, lea, addps, addss などにも
全て影響する貴重な間接オペランド。
149:デフォルトの名無しさん
18/08/23 08:46:40.08 4LRopBJn.net
>>147
8086時代の 64KB では制限が大きすぎて、ほとんどのプログラムで、制限が足かせ
になっていたので、32BIT になって、アドレスが 4GB に拡張されて非常に便利になった。
ところが、64BIT 時代になっても、そのときのようなメリットが無いと思うんだ。
AMD vs Intel の競争の結果出てきた産物かも知れない。そういうの、時々ある。
150:デフォルトの名無しさん
18/08/23 08:56:25.66 K9a3gVgQ.net
>>145
WindowsではASLRでランダム化普通にやってるらしいですよ
URLリンク(07c00.hatenablog.com)
OSがプロセスをロードするときに、ランダムな場所にモジュールを配置するセキュリティ機能です。
実際はモジュールだけじゃなく、スタックやヒープなどもランダマイズされたりします。
151:デフォルトの名無しさん
18/08/23 09:03:22.89 4LRopBJn.net
>>150
少なくとも、EXE の .text, .data セクションは再配置される事は無いはず。
なぜなら、.reloc section が存在せず、再配置する事が原理的に出来なくなっているから。
DLL は、.reloc section が残されているので再配置できる。ただし、再配置しなくても、
全てのシステムのDLLは、最初からアドレスが重ならないような ImageBase になっている
ので、再配置されずにそのままおかれるのが、昔は基本であった。
152:デフォルトの名無しさん
18/08/23 10:25:25.69 3bgfj1QZ.net
>>148
64bitコードで絶対番地に依存したコードとか
考え方が古いねえ
ていうか、
イヤなら2GB限定のコードにすればいい
コードもデータも2GBの範囲に割り当てられるから
153:デフォルトの名無しさん
18/08/23 11:01:43.32 4LRopBJn.net
>>152
じゃあなんで、MS純正VSは、いまだに 32BIT コードで動いてるのさ。
x64 は、レジスタが増えた事と、memmove() などが多分、倍の速度で動く事が
最大のメリットじゃないの?
アドレス幅が64BITになって現実的なメリットはどこにあるのかな?
154:デフォルトの名無しさん
18/08/23 11:36:32.13 3bgfj1QZ.net
なにが「じゃあ」だか
メリットが無いと思うなら2GB限定のアプリにすれば良い
って書いたのが見えなかった?
155:デフォルトの名無しさん
18/08/23 12:51:14.26 4LRopBJn.net
>>154
だから、メリットはあるよ。
レジスタが増えること、AVX, AVX2, AVX512 で、YMM, ZMM レジスタでベクトル
の次元が大きくなったSIMD 命令が使えること、3オペランドの以上のSIMD命令が使える
事、メモリ転送の速度が倍近くになること。malloc(), new が、2GB を超えて行える事。
初期化サイズが2GBを越えるメリットは余り無いと思ってるけど。
156:
18/08/23 17:09:15.42 NMfUyUL+.net
>>149
アドレス空間は広いほうがいいに決まっている
ユーザーアドレス空間の断片化は基本防止できない、だったら入れものが広いほういい
157:
18/08/23 17:09:45.22 NMfUyUL+.net
>>153
>>156
158:デフォルトの名無しさん
18/08/23 18:36:50.55 wxGNRrqx.net
>>155
2G限定と関係ないじゃん
159:デフォルトの名無しさん
18/08/23 19:03:15.16 sOVf8lyT.net
>>148
結局、
mov al,my_mojiretu[rbx]
こんなコードを書くと64bitではLINKする時にエラーが出る
/largeaddressaware:noを指定するとLINKでエラーは出なくなるが、
/largeaddressaware:noを指定すると動的メモリも含め2GB以下のメモリしか扱えなくなる
160:デフォルトの名無しさん
18/08/23 19:09:33.40 QrjyoFcH.net
なんかしらあるんじゃね
161:デフォルトの名無しさん
18/08/23 19:30:53.52 k97Awv43.net
>>159
それでいいじゃん
何種類作るつもりだよ
162:デフォルトの名無しさん
18/08/23 19:47:44.13 sOVf8lyT.net
32bit Windowsは切り捨てに入ってきてるからね
ゲームでも64bit版のみのも出てきてる
NVIDIA、GPUドライバーの32bit版OSサポートを終了へ ~次期版からは64bit版だけに
URLリンク(forest.watch.impress.co.jp)
163:デフォルトの名無しさん
18/08/23 19:52:19.27 sOVf8lyT.net
バーチャルYoutuberなんかでも使われるソフト(エロゲ)だが
64bit Windowsのみ対応
動画配信などで結構使われてる
CUSTOM ORDER MAID 3D2
URLリンク(com3d2.jp)
OS Windows® 7/8.1/10 全て64bitのみ対応 ※6
※6:32bitOSには対応しておりません。
164:デフォルトの名無しさん
18/08/23 20:04:05.41 k97Awv43.net
>>162
いや、
32bit/64bitアプリの話じゃなくて
64bitの2GB制限/制限なしアプリの話
165:デフォルトの名無しさん
18/08/23 20:05:15.44 sOVf8lyT.net
>>153
10年位前に出来たオンラインゲームでも、今はもう2GBのメモリだともう足りなくて
32bitのゲームでも/LARGEADDRESSAWAREのフラグ立てて延命してるのもあるよ
64bit WindowsならLAAフラグを立てると32bitアプリでも4GBまで使えるようになる
LAAで延命してるゲームで32bit Windowsで遊ぶとメモリ不足で高確率で落ちるゲームとか既にある
166:デフォルトの名無しさん
18/08/23 20:12:15.30 sOVf8lyT.net
こんな記事が出るくらい、2GBではメモリが足りなくなってるアプリがたくさんあるぞ
64bit Windowsを前提とした32bitアプリケーション延命法
~ LAAオプションで32bitアプリケーションのメモリ不足問題を解消
URLリンク(www.webtech.co.jp)
167:デフォルトの名無しさん
18/08/23 20:12:19.28 k97Awv43.net
なぜ確率の問題?
168:デフォルトの名無しさん
18/08/23 20:16:43.95 sOVf8lyT.net
ちなみにこのブログ書いてるところはWindows用ソフトもいくつか出してるところだよ
169:デフォルトの名無しさん
18/08/23 20:18:49.99 sOVf8lyT.net
>>167
>>165のこと?
一応、32bitWindowsもサポートしてるがメモリが足りなくなってよく落ちるので
実際は64bit Windowsでしかまともに遊べないってこと
そういうゲームが既にある
170:デフォルトの名無しさん
18/08/23 20:23:47.22 k97Awv43.net
質問に全く答えてない件
171:デフォルトの名無しさん
18/08/23 20:34:21.09 sOVf8lyT.net
>>146
実際にどの程度、速度が変わるのか試してみて欲しいもんだな
ただの机上の空論じゃないのか?
大体、配列で何回もデータにアクセスするなら
32bitのDISPを毎回指定するオーバヘッドだってあるんだが
172:デフォルトの名無しさん
18/08/23 21:08:22.26 wxGNRrqx.net
32bitアプリも2G限定アプリも32bit OSも絶滅して良い
Windowsの話
173:デフォルトの名無しさん
18/08/23 21:13:40.67 sOVf8lyT.net
mov rcx, offset HOGEHOGE01
mov rax, qword ptr [rcx + rbx]
mov rax, qword ptr [rcx + rbx]
mov rax, qword ptr [rcx + rbx]
mov rax, qword ptr [rcx + rbx]
これと
mov rax, HOGEHOGE01[rbx]
mov rax, HOGEHOGE01[rbx]
mov rax, HOGEHOGE01[rbx]
mov rax, HOGEHOGE01[rbx]
これを250個並べて1000万回ループさせてみたが、1%くらいしか差はないよ
174:デフォルトの名無しさん
18/08/23 21:28:42.56 wxGNRrqx.net
250個並べてキャッシュに収まる?
175:デフォルトの名無しさん
18/08/24 00:12:57.34 568m+iHd.net
なんで訳分からなくなりそうになったのか理解できたw
4LRopBJnが変なんだな。
Microsoftが64bitでは絶対アドレスのインデックスは使わないって決めたんだから、その流儀に従うのが高級言語とリンクだよ。
176:デフォルトの名無しさん
18/08/24 00:23:58.73 568m+iHd.net
>>167
メモリが厳しいなら、ヒープが断片化すればメモリ確保できなくなっても不思議じゃないよ。
それなら確率的に落ちると思う。
177:デフォルトの名無しさん
18/08/24 01:48:40.54 PMMpdZPT.net
>>158
意味不明。
何の事言ってるの?
178:デフォルトの名無しさん
18/08/24 01:50:43.81 PMMpdZPT.net
>>159
いや、それはあなたの勘違い。
そのオプションを指定しても、EXEの中に入っている「初期化データ」のアドレス
が2GB以下に限定されるだけで、動的メモリは、理論上は、100GB でも一気に
確保できる。それは、再三言ってる。あなたは理解出来てないと思う。
179:デフォルトの名無しさん
18/08/24 01:54:49.18 PMMpdZPT.net
>>164
再三言ってるけど、あの/LARGEADDRESSAWARE:NO オプションを
付けても、「初期化データ」のアドレスが2GBに制限されるだけで、
new や malloc() などの、ヒープから確保される動的メモリは、64GBの
アドレス空間どこにあっても問題ないんだよ。
180:デフォルトの名無しさん
18/08/24 02:00:34.30 PMMpdZPT.net
>>173
そりゃ分かってるよ。
でも逆に、EXEファイルの中に最初から入っている「初期化データ」
の2GB制限とどっちが良いかの話になるんだよ。もちろん、動的メモリ
は何の制限も受けず、64GBアドレスが好きなように使える。
初期化データというのは、何かの埋め込みテーブルのための配列
だとか、文字列データとか、そういうものだよ。
巨大な3Dモデルデータ、テクスチャ、マップデータなどは、外部ファイル
にでも置いておけば、2GBの制限は受けず、仮想アドレスとしては
64BITまるまる使えるから。
実際、EXEの中にある初期化データが2GBを越えるという事は、
EXEファイルが2GBを越えるという事だから、そのアプリの起動
時には、有無を言わさず HDDなどから、2GBの読み込みが
始まってしまうことになる。
181:デフォルトの名無しさん
18/08/24 02:02:34.25 PMMpdZPT.net
>>179 >>180
【誤字訂正】
誤:64GBアドレス
正:64BITアドレス
言葉は間違っているが、中身は間違ってない。数学は100点、国語は赤点
の学生時代だったし。
182:デフォルトの名無しさん
18/08/24 02:18:09.88 PMMpdZPT.net
>>173
それでもやはり、1%の速度低下にはなったんだよね。
「初期化データの2GB制限」は、現実的には何の制限にもなってない
事は理解出来てる???? 動的メモリは、64BIT 自由に使える
んだよ。
183:デフォルトの名無しさん
18/08/24 04:19:33.40 CXKCSzYg.net
>>178、179
実際にやってみれば?
C言語でmallocでもvirtualallocでも
/largeaddressaware:noを付けると動的メモリも2GB以下しか確保できなくなるから
184:デフォルトの名無しさん
18/08/24 04:38:15.52 CXKCSzYg.net
>>182
実際に試したことないのが丸わかり
/largeaddressaware:noをつけると本当に試してみるといいよ、
動的メモリも2GB以下しか確保できなくなるから
このページの
URLリンク(www.webtech.co.jp)
この図に載ってるプログラムでも試せるよ
URLリンク(www.webtech.co.jp)
185:デフォルトの名無しさん
18/08/24 04:39:04.29 CXKCSzYg.net
上のプログラムだと/largeaddressaware:noを付けない時に
無限に確保するので4500MBで終わるように少し改変してみた
これで試してみな
#include <windows.h>
int PASCAL WinMain(HINSTANCE hinst, HINSTANCE hprev, LPSTR cmd, int n)
{
int step = 10; //10MB
int count = 0;
char temp[20];
for (;;)
{
void *p = GlobalAlloc(GPTR, step * 1024 * 1024);
if (p == NULL)
{
break;
}
count++;
if(count > 400 + 50) {
break;
}
}
wsprintf(temp, "Total %d MB\n", count * step);
MessageBox(NULL, temp, "alloc test", MB_OK);
}
186:デフォルトの名無しさん
18/08/24 04:45:01.40 CXKCSzYg.net
上のプログラムは64bitでも、32bitでもコンパイルは通るよ
187:デフォルトの名無しさん
18/08/24 05:30:48.46 CXKCSzYg.net
そもそもWindowsは/largeaddressaware:noを付けなくても静的データは2GBまでしか使えない
動的データだけがOSが対応してるメモリ分だけ制限なく使える
WindowsにはLinuxのgccのような-mcmodel=largeや-mcmodel=mediumのようなオプションは存在しない
/largeaddressaware:noを付けると64bitアプリでも動的メモリも含めてすべてのメモリで2GB以下までしか使えなくなる
PGIのコンパイラのページでわかりやすく解説してあるよ
URLリンク(www.softek.co.jp)
188:デフォルトの名無しさん
18/08/24 07:19:19.64 ZkSPfVdV.net
>>173
これは最適化を知らないコード
250個並べちゃいけない
189:デフォルトの名無しさん
18/08/24 07:30:57.16 ZkSPfVdV.net
>>182
そこだけ抜き出して、
しかも最適化してないコードで1%
こんなコードは全体の中では非常にわずかだろうし
タイムクリティカル部分であれば最適化される
実質差が無いメリットの為に絶対アドレスに依存したコードにする
時代に逆行だ
それでも逆行したければ
0~2Gのアドレスしか割り当てられない2G限定アプリにしろ
190:デフォルトの名無しさん
18/08/24 07:35:38.16 CXKCSzYg.net
>>188
250個並べても7KBくらい
1次命令キャッシュに丸ごと収まるぞ
191:デフォルトの名無しさん
18/08/24 07:38:24.94 ZkSPfVdV.net
uOPキャッシュ
192:デフォルトの名無しさん
18/08/24 07:53:32.13 CXKCSzYg.net
>>191
25個並べることにしてループ回数を一桁増やしたが早くならないぞ
そういうのを机上の空論というんだ
193:デフォルトの名無しさん
18/08/24 07:59:52.52 568m+iHd.net
なんか初心者スレの趣旨とずれまくりなんだけど。
コンパイラのABIが「変わった」のなら、それに合わせたのを紹介しないと。
Visual Cは64bitではインラインアセンブラも使えなくなったし、AVXやSSEは組み込み関数で大概は満足できるはずって判断されたのだろう。
今のご時世わざわざアセンブリ言語でプログラミングしたいって用途は動画のコーデックやフィルタプラグインDLL、将棋とかの思考ルーチンとかでしょ。
こういうのは2GB制限下でしか使えないコードでは困るはず。
194:デフォルトの名無しさん
18/08/24 08:09:12.98 568m+iHd.net
>>189
静的配列だとサイズが決まってるから、恐らく最適化されてポインタとオフセット(ディスプレースメント)に変換されるよね。
>実質差が無いメリットの為に絶対アドレスに依存したコードにする
>時代に逆行だ
これに同意。
195:デフォルトの名無しさん
18/08/24 12:53:22.92 7MrYBE0R.net
>>192
ヒント HTT
196:デフォルトの名無しさん
18/08/24 14:52:13.41 PMMpdZPT.net
>>185
自分は 64BIT 用C/C++コンパイラをインストールして無いので、試せません。
link.exe に、 /largeaddressaware:no を渡した場合にのみ、
GlobalAlloc() が失敗する理由は何ですか?
ポインタが32BITになる? それとも、GlobalAlloc の関数が別のものに
入れ替わってしまう?
そのどちらでもないとしたら何が原因ですか?
197:デフォルトの名無しさん
18/08/24 14:54:32.88 PMMpdZPT.net
>>187
>/largeaddressaware:noを付けると64bitアプリでも動的メモリも含めてすべてのメモリで2GB以下までしか使えなくなる
>PGIのコンパイラのページでわかりやすく解説してあるよ
>URLリンク(www.softek.co.jp)
リンク先のページを見たのですが、自分には、
「動的メモリの場合にも2GB以下しか使えなくなる」
という文書が見つかりませんでした。
どこに書かれているか、ご指摘いただければ幸いです。
198:デフォルトの名無しさん
18/08/24 16:51:48.72 VlbdtNmU.net
実験したけど2GBまでだったよ
malloc
アドレスは32bitで保持出来る
32bitアプリからの移植用だろうね
199:デフォルトの名無しさん
18/08/24 16:55:58.09 VlbdtNmU.net
>>196
メモリはOS側の管理でしょ?
OSがアプリ種別を判別してアドレスを割り当てる
31bit
32bit
64bit
の3種類かな?
200:デフォルトの名無しさん
18/08/24 17:07:40.76 PMMpdZPT.net
>>199
リンカオプションによって、API の挙動まで変わってしまうんでしょうか。
そして、Win64 API の GlobalAlloc() などが返す値が 31 BIT までに
なるので、malloc() もそれにつられて、勝手に 31BIT までになると?
64BIT COFF だと、COFF Image に、/largeaddressaware:no かどうか
を示す BIT か何かが追加された???
201:デフォルトの名無しさん
18/08/24 19:11:45.47 5OB8VNk6.net
>>196
無料のVisual Studio Expressでも2013以降は64bitのビルドにも対応してるよ
64bitのWindowsプログラミングに興味があるなら入れてみれば?
プログラムのコードを見ればわかるように
10MBずつメモリを確保していき
メモリが確保できなくてGlobalAllocの戻り値にNULLが返るか
確保したメモリが4500MBを越えたらbreakでループを抜けて
確保したメモリ容量を表示して終了するようになってる
で、/largeaddressaware:noを指定すると
俺の環境では1970MB確保したところでループを抜けて終了してる
つまり、1970MB確保したところで、
次にGlobalAllocを実行するとメモリが確保できなくてNULLが返る
これは、動的メモリも2GB以下しか確保できないということを示してる
/largeaddressaware:noを指定せずにコンパイルすると
4510MBまで確保して終了する
202:デフォルトの名無しさん
18/08/24 19:16:32.91 5OB8VNk6.net
>>200
Visual Studioに入ってるdumpbin.exeでコマンドプロンプトで
dumpbin /headers hogehoge.exe
とやると/largeaddressawareを指定した状態(/largeaddressaware:noを指定しない状態)だと
FILE HEADER VALUESの項目とのところに
Application can handle large (>2GB) addresses
これが表示される
なので詳しくは知らないが実行ファイルの中に/lageaddressawareの指定をする部分があるはず
これまたVisual Studioに入ってるeditbin.exeを使うと
実行ファイルそのものに/largeaddressawareや/lageaddressaware:noの指定ができる
LAAを有効にするには
editbin /lageaddressaware hogehoge.exe
LAAを無効にするには
editbin /lageaddressaware:no hogehoge.exe
203:デフォルトの名無しさん
18/08/24 19:47:12.65 568m+iHd.net
VCで64bitの静的配列にアクセスするコードを調べてみた。
#include <math.h>
volatile char str[1024];
volatile char c;
main(int argc, char *argv[])
{
int idx;
idx = (int)(rand() * 1024);
c = str[idx];
}
これの配列アクセス部分が
; 11 : c = str[idx];
0001c 48 63 44 24 20 movsxd rax, DWORD PTR idx$[rsp]
00021 48 8d 0d 00 00
00 00 lea rcx, OFFSET FLAT:str
00028 0f b6 04 01 movzx eax, BYTE PTR [rcx+rax]
0002c 88 05 00 00 00
00 mov BYTE PTR c, al
00028は[rcx+rax]で配列アクセスしてる
そして、00021と0002cはrip相対アドレッシングだよね?(エンコードは自信ないので)
204:デフォルトの名無しさん
18/08/24 19:58:50.48 568m+iHd.net
>>198
時々ポインタをDWORDに変換して構造体に突っ込んでたりすることがあるからね。
argeaddressawareは、こういうコードが含まれたアプリをどうしても64bitで動かさなきゃいけなくなった時とかに仕方なく使うオプションでしょう。
でないと、GlobalAlloc()が大きなアドレス返したら動かなくなるし。
205:デフォルトの名無しさん
18/08/24 20:08:42.11 568m+iHd.net
>>200
プロセスを起動する時にexeのLAAフラグを見てメモリとかハンドルを返すAPIが32bitに収まる値を返すように設定されるんだと思う。
こういうのはプロセスごとに32bitとかにも切り替えられる(この場合はシステムDLLは64bitとは別だけど)ので、
互換性を確保する仕組みが裏で動いてるはずだよ。
206:デフォルトの名無しさん
18/08/24 20:18:03.36 568m+iHd.net
>>203のコードバイトの折り返し部分のタブが詰められて見にくいので
0001c 48 63 44 24 20 movsxd rax, DWORD PTR idx$[rsp]
00021 48 8d 0d 00 00 00 00 lea rcx, OFFSET FLAT:str
00028 0f b6 04 01 movzx eax, BYTE PTR [rcx+rax]
0002c 88 05 00 00 00 00 mov BYTE PTR c, al
207:デフォルトの名無しさん
18/08/24 21:46:35.00 5OB8VNk6.net
>>203
VC++だと/FAオプションを指定するとアセンブラ出力もされるよ
ただ、64bitのVC++コンパイラが吐き出すアセンブラコードは
そのままではml64.exeでアセンブルできないけど
ml64.exeでアセンブルできるように修正できたらml64.exeでアセンブルする時に
/Flオプションを指定するとリスティングファイルを出力してくれる
208:デフォルトの名無しさん
18/08/24 22:08:39.28 568m+iHd.net
>>207
>>203は/FAscで出力された.codから抜粋したもので、リンク前だから変数のアドレスが変な値になってる。
最適化オプションつけ忘れてるのでimul使ってるけど、/O2でも配列へのアクセスはインデックスレジスタ付きなのは変わらなかった。
このサンプルでは配列の添え字がコンパイル時に推定できないようにしたのでインデックスレジスタ付きになってるけど、
普通のループでは、この部分は最適化されてポインタに変更されて、レジスタ間接とポインタ操作するコードになるはず。
209:デフォルトの名無しさん
18/08/25 04:35:15.70 gxBSyOuw.net
プロセスのアドレス空間が、4GB までだから
その内、Linux では1GB、Windows では2GB を、カーネル空間に割り当てているから、
残りのユーザー空間は、3GB, 2GB になる
カーネル空間は、全プロセス共通の空間だから、各プロセスで使えないアドレス
210:デフォルトの名無しさん
18/08/25 05:52:55.11 5KTEEpUR.net
64bit Windowsでの2GB制限ってのは、単にメモリ確保時のアドレスの割り当て方やハンドルの値が変わるだけで、
アクセスできない場所では普通に例外が発生するだけのこと。
/largeaddressaware:yesの状態では、32bitの範囲のアドレスがが割り当てられてないから
rip相対を使って静的変数のあるアドレスを取得するってことね。
211:デフォルトの名無しさん
18/08/25 05:57:44.86 5KTEEpUR.net
割り当てられてないってのは変だったね。
アクセス権限が与えられてないからってこと。
212:デフォルトの名無しさん
18/08/25 11:07:20.24 auNeFg4G.net
偉そうなもんだな。
もうちょっと、言い方ってもんを学んだ方がいい。
人間性に問題あるかも。
213:デフォルトの名無しさん
18/09/03 04:21:34.86 A+X9ST7o.net
アセンブラの命令を覚えたいのと
デバッガーを使いこなしたいんですが
何かお勧めの勉強方法はありますか?
C入門程度だけの知識だけでアセンブラは全く知りません
よろしくお願い致します
214:デフォルトの名無しさん
18/09/03 11:24:23.57 dhYkuZhG.net
CPUは何?
215:デフォルトの名無しさん
18/09/03 12:38:16.62 f+M/nyW5.net
書いてないってことは決まって無いんだろう
Visual Studio Community 2017
x86 64bit
ml64.exe
が環境としては一番簡単かな
何もしない関数をアセンブラで作って
Cからその関数を呼ぶところから始めよう
216:デフォルトの名無しさん
18/09/03 20:27:11.25 A+X9ST7o.net
os10 64bitです
C++でアセンブラ使えるんですね
知りませんでした。そこら辺も調べてみます
デバッガーでコードを読んで書き換えられるようになりたいです
217:デフォルトの名無しさん
18/09/03 20:36:15.47 i7qE7EE1.net
マカーか
218:デフォルトの名無しさん
18/09/04 16:50:20.52 ErgP6cOz.net
横からだけど、
それに必要なのはバイナリからアセンブラコードを出力する逆アセンブラじゃないの?
それとも基礎知識として習得したいってことなのか
219:デフォルトの名無しさん
18/09/04 17:01:04.80 hMkkrsf+.net
チートしたい!
220:デフォルトの名無しさん
18/09/04 22:32:50.81 snmgssEj.net
>>218
これから勉強するって段階で逆アセはまだ早い。まずCで簡単なコード書いてアセンブラソース出力
それを見て少しずつ変更して動作を勉強。どきどき暴走させて遊ぶのがいい。
Cやアセンブラのソースがないバイナリを逆アセしても、逆アセはコードとデータの区別なしにコード化するから混乱する。
221:デフォルトの名無しさん
18/09/04 22:50:42.54 bj+tb6HS.net
回答ありがとうございます;
アセンブラの実行環境整える(実機だのエミュだの)用意するのが物凄い敷居高そうに感じるので
チートエンジンやollydbg?ってやつでオフライン用のゲームでも解析しながら
アセンブラ命令群を覚えようと思ってます。
アセンブラの命令を覚えるのだけなら後者でも力つきますかね?目標はウイルスのデバッグとか出来るようになりたいです
222:デフォルトの名無しさん
18/09/05 01:22:32.69 vQx16S6k.net
>>221
>目標はウイルスのデバッグとか出来るようになりたいです
どうしてそう反社会的な方ばっかり目がいくんだい。
これだから、ハッカー=クラッカー、悪者、のイメージが付く。
昔は、アセンブラといえば、速さのために学んだものなのに。
君みたいなのにはプログラムになんか興味を持たないで欲しい。
223:デフォルトの名無しさん
18/09/05 02:37:54.86 wyXCwUhn.net
>>どうしてそう反社会的な方ばっかり目がいくんだい。
そう…ではなくてですね
将来ウイルスとかランサムウェアの対策ツールとか作ってみたいから
デバッグスキル付けたいと思って、覚えたいと思いました。
URLリンク(www5c.biglobe.ne.jp) 見て実行環境頑張って作って覚えようと思ったんですけど
とっつきづらすぎると思って;
てかVisualStudioって自分のコードアセンブラで出力したり出来るんですね
全然知りませんでした。ありがとうございます
224:デフォルトの名無しさん
18/09/05 03:52:48.57 EatH13os.net
ウィルスってね、勉強のつもりで作っても、いざ出来上がると使ってみたくなるもんなんだよね。
そういう誘惑に勝てるかどうか
225:デフォルトの名無しさん
18/09/05 06:27:13.70 wyXCwUhn.net
>>224
そういう方もいらっしゃるんですね。
プログラミング歴はもといパソコンも初心者レベルにしかない自分には縁のない響きですね・・
ところでC++のコードをvisualstudioでアセンブラ出力とはどうやるんでしょうか?
気になって調べてみたんですが デバック(D)→ウィンドウ→アセンブラ っと進むと出てくると書いてあるんですが
そんな項目ありません;
226:デフォルトの名無しさん
18/09/05 11:13:33.31 /V9AsOwQ.net
debug.exe
debug64.exe
227:デフォルトの名無しさん
18/09/05 11:34:16.13 TWmx8fnR.net
OllyDbg とか、
うさぴょんの「うさみみハリケーン・スペシャルねこまんま」とか、
将棋AI「やねうら王」の作者、やねうらおの本「解析魔法少女 美咲ちゃん」とか
デバッガによるx86プログラム解析入門 【x64対応版】、うさぴょん、2014
228:デフォルトの名無しさん
18/09/05 11:55:15.09 gDSR0MtA.net
>>225
ソリューションエクスプローラーでソリューションの下にあるプロジェクトを選択してプロパティ
構成プロパティ→C/C++→出力ファイル→アセンブリの出力
229:デフォルトの名無しさん
18/09/05 20:44:59.69 wyXCwUhn.net
>>227-228
ありがとうございます
ソリューション周辺探しましたが URLリンク(gyazo.com)
無かったです……
VSインストールする時2つくらいしか選択しなかったんですがそれがまずかったんでしょうか
ollydbgというのも調べてみます
230:デフォルトの名無しさん
18/09/06 01:20:57.16 UZSBUUik.net
VSでC/C++のデバッギングに入ってステップインしてたらアセンブラのコードが出てこないか?
231:デフォルトの名無しさん
18/09/06 01:24:39.50 uY3Jh6lT.net
>>229
C/C++の所のツリー開け
232:デフォルトの名無しさん
18/09/06 05:22:06.40 psScFFtw.net
Cならインラインアセンブラ使えば良いんでない?
233:デフォルトの名無しさん
18/09/06 14:49:24.96 jOmc1UUP.net
いや、普通にターゲットCPUのニーモニック表を探して来て見ろよ
234:デフォルトの名無しさん
18/09/24 01:13:48.37 rSek34EX.net
取り敢えずアセンブラ上の数字2進数(或いは16進数)を桁ごとに分けて十進数にして、+30して(文字コードに変換)する事には成功した。
何進数か関係無く、10の位なら10ずつ、100の位なら100ずつ引いて実現。
筆算のアルゴリズムだともっと速いらしいので、時間があれば挑戦したい。
時間があれば。。。
235:デフォルトの名無しさん
18/09/24 01:17:43.11 rSek34EX.net
x 何進数か関係無く、10の位なら10ずつ、100の位なら100ずつ引いて
o 何進数か関係無く、(何進数の10でも10進数の10だと言うことは変わらないので)10の位なら10(16進数だとA)ずつ、100の位なら100ずつ引いて
236:デフォルトの名無しさん
18/09/25 01:58:20.74 4rHiZGxF.net
8bitISAの経験はあるんだがIA32やAMD64のプログラミングマニュアルを見ると命令の多さにめまいがする
しかもググってみるとメモリアドレッシングもなにやら作法があるようでよくわからん・・・
な状態なのだがIA32/AMD64のアセンブラを勉強するのにおすすめの資料とかあるかな
今のところ自力で書いたことのあるISAは78K0S、8051、AVR。基本的な概念はわかっているつもり
リンカ周りは不安あり。プラットフォームはWindowsかLinuxかFreeBSDを検討中
237:デフォルトの名無しさん
18/09/25 08:56:01.40 oRUMH9qn.net
>>236
ISAって何のこと?
238:デフォルトの名無しさん
18/09/25 09:25:52.53 oRUMH9qn.net
ISA=instruction set architecture=命令セットアーキテクチャ
や、
ISA=PC/ATの拡張スロットのバス仕様
??
239:デフォルトの名無しさん
18/09/25 18:37:53.38 oPuX37oa.net
このスレでISAをIndustry Standard Architectureと解釈する必要ってあるのか?
240:デフォルトの名無しさん
18/09/26 04:10:17.53 GMLyVXjl.net
誤解を生まないよう書き込む際は気を付けた方がいいね
241:デフォルトの名無しさん
18/09/26 10:35:31.91 s/2dxbJy.net
>>236
VCのx64はインラインアセンブラも使えなくなってるんだから、特殊なビット操作やりたいのでなければ
組み込み関数覚えてからの方が楽なんじゃないの
URLリンク(software.intel.com)
右端に対応するニーモニックが書いてある
242:デフォルトの名無しさん
18/09/27 10:28:07.85 +X2PETpr.net
>>240
アスペじゃなければこの文脈でそれはない
243:デフォルトの名無しさん
18/09/27 10:47:26.07 JRG0evD8.net
そもそも8bitISAなんて言い方は一般的ではないもん。
244:デフォルトの名無しさん
18/09/27 10:58:42.91 JRG0evD8.net
かなりアセンブラ経験あるけど、8bit ISAと聞いても意味が分からなかった。
多分、8bit CPUとか、8bit マイコンのことが言いたかったのではないかとは
思ったけど、意味がはっきりしなかったので念のため聞いてみた。
個人的には、Instrucstion Set Architectureの意味での「ISA」という
言い方は、Intelのマニュアルなどで最近目にするようになった印象が
ある言い方。
修正に告ぐ修正を重ねてが複雑化したx86系CPUのあの複雑さのニュアンス
を出すためにIntelが使い始めた言葉かもしれない。
昔、Z80が流行っていたころは、日本の雑誌などでは、8bit CPUと言われて
いたし、炊飯器や冷蔵庫では、今でもCPUよりもどちらかというと
I/OポートやA/Dコンバーターを内蔵しているみたいななニュアンスを
含めて「マイコン」と言われていると思う。
ISAという言葉は、Intelマニュアル以外ではあまり見たことない。