NAKAMURA Minoru の日記 (2009年10月)

先月の日記(2009年09月) 今月の日記(2009年10月)
2002 | 10 | 11 | 12
2003 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2004 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2005 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2006 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2007 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2008 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2009 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2010 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2011 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2012 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2013 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2014 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2015 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2016 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2017 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2018 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2019 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2020 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2021 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2022 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2023 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2024 | 1 | 2 | 3
ホームページ | 最新のコメント50
インデックス: 食べ歩き | Java | プログラム | UNIX | 画像
最新の日記へのリンク | この日記ページをはてなアンテナに追加 この日記ページをはてなブックマークに追加
はてな ダイアリー アンテナ ブックマーク ブログ
Twitter | mixi | Facebook | slideshare | github | Qiita



10/21 (水)

[CPU] AMD64 と Intel64 の仕様の違いか、単にマニュアルが間違っているだけなのか

Intel の Intel64 のマニュアルの 64ビット拡張(IA-32e)の説明は誤字が多いし説明が雑すぎる。というお話。

ストリング命令の rDI レジスタは ES セグメントを受けるか否か

x86 にはストリング命令と呼ばれる便利な命令が存在する。 これは CL レジスタで指定された回数だけメモリ転送・メモリ比較を連続実行する命令だ。 memcpy などを作るのに重宝する。

ストリング命令はオペランドを持たず、SI レジスタと DI レジスタを暗黙のうちに使用する。 例えば MOVB/MOVW 命令は SI レジスタが指すメモリから DI レジスタに指すレジスタの指すメモリに 1バイト/2 バイトの転送を行なう。

問題はストリング命令にセグメントオーバライドを行った場合だ。 MOVB/MOVW 命令の SI レジスタの方は通常通り DS セグメントによって修飾されるが、DI レジスタは ES セグメントによって修飾されている。 セグメントオーバーライドは DS セグメントを切り替えるので、SS: MOVSB なら SS:SI → ES:DI への転送になる。

32 ビット拡張

8086 が i386 (IA-32) に拡張される時に 16 ビットレジスタ(SI, DI)が 32 ビットレジスタ(ESI, EDI) に拡張された。 一方、セグメント修飾のルールは変更されなかった(セグメントレジスタは FS と GS が追加されたが)。 つまりストリング命令は DS:ESI と ES:EDI を使うようになったが、セグメントオーバーライドは DS:ESI に適用され ES:EDI には影響がなかった。

64 ビット拡張

AMD が IA-32 を 64 ビット化して x86-64 というか AMD64 を作った時に、レジスタはさらに 64 ビット化(RSI, RDI)された。 一方、セグメント機構は大幅に簡略化され、CS, DS, ES, SS セグメントはセグメントベースが 0 となり、実質的にゲタを履かせる機能がなくなった(effective address = linear address になった)。 ただし FS と GS の 2 つだけはゲタ機能が残った。

疑問

64 ビットモードの RDI は ES 修飾を受けるのだろうか? あるいは MOV(S/W/D/Q) 命令はセグメントオーバライドで RDI を修飾するセグメントが切り替わるだろうか?

まず Intel64 and IA-32 Architectures Software Developer's Manual Volume 1: Basic Architecture を見てみる(下線は引用者)。

7.3.10 String Operations in 64-Bit Mode
The behavior of MOVS (Move String), CMPS (Compare string), SCAS (Scan string), LODS (Load string), and STOS (Store string) instructions in 64-bit mode is similar to their behavior in non-64-bit modes, with the following differences:
  • The source operand is specified by RSI or DS:ESI, depending on the address size attribute of the operation.
  • The destination operand is specified by RDI or DS:EDI, depending on the address size attribute of the operation.
  • Operation on 64-bit data is supported by using the REX.W prefix.

64ビットモードのストリング命令は非64ビットモードと同じらしい、って良く読むとEDI は DS セグメントレジスタになっている。でも RDI の場合はセグメントが付いてない。

命令仕様書の MOVB 命令のところはIntel64 and IA-32 Architectures Software Developer's Manual Volume 2A: Instruction Set Reference, A-M の 3-716 にある。 表中には 64 ビットモードでは RDI または EDI を使いますと書いてある。

Description にはまず以下のような記述がある(下線は引用者)。

Moves the byte, word, or doubleword specified with the second operand (source operand) to the location specified with the first operand (destination operand). Both the source and destination operands are located in memory. The address of the source operand is read from the DS:ESI or the DS:SI registers (depending on the address-size attribute of the instruction, 32 or 16, respectively). The address of the destination operand is read from the ES:EDI or the ES:DI registers (again depending on the address-size attribute of the instruction). The DS segment may be overridden with a segment override prefix, but the ES segment cannot be overridden.

上記は非64ビットモードでの断り書きで、64ビットモードの特例は続き、セグメント修飾抜きの EDI/RDI が出てくる。 つまり表と同じね。 ここまでを読む限りストリング命令の中の EDI/RDI は ES セグメント修飾がないと思われる。

In 64-bit mode, the instruction's default address size is 64 bits, 32-bit address size is supported using the prefix 67H. The 64-bit addresses are specified by RSI and RDI; 32-bit address are specified by ESI and EDI. Use of the REX.W prefix promotes doubleword operation to 64 bits. See the summary chart at the beginning of this section for encoding data and limits.

一方、AMD 側の資料にあたる。 AMD64 Architecture Programmer's Manual Volume 3: General-Purpose and System Instructions Rev 3.14 の 168 ページを引用する(下線は引用者)。

Moves a byte, word, doubleword, or quadword from the memory location pointed to by DS:rSI to the memory location pointed to by ES:rDI, and then increments or decrements the rSI and rDI registers according to the state of the DF flag in the rFLAGS register.
(中略)
The forms of the MOVSx instruction with explicit operands address the first operand at seg:[rSI]. The value of seg defaults to the DS segment, but can be overridden by a segment prefix. These instructions always address the second operand at ES:[rDI] (ES may not be overridden). The explicit operands serve only to specify the type (size) of the value being moved.

こちらの資料は非64ビットモードと64 ビットモードによる区別がないのだが、RDI は ES セグメント修飾を受けていると読める。 正しいのはどっちなんだ。 あるいは Intel64 と AMD64 の違いなのか?

追記:2012/05/29

これは AMD の記述の方が正しく、Intel の CPU でも MOVS DS:RSI, ES:RDI になっている(Xeon X5670 で確認)。

命令の SIB フィールドのベースレジスタ指定の未使用の特例

もう一つ。 x86-64 命令の命令フォーマットである ModR/M と SIB に絡む問題がある。

x86 命令は [r8] のようなベースレジスタを1つだけ使った 1レジスタのメモリアドレスの指定方法と、[r8 + r9 * 4] のようにベースレジスタとインデックスレジスタ×スケールを使った2レジスタのメモリアドレスの指定方法がある。 前者は(基本的に)命令の中の ModR/M バイトだけを使い、後者は ModR/M バイトに加えて SIB バイトを使うことでアドレス指定部分が 2 バイトになる。 SIB バイトを使うかどうかの選択は ModR/M バイトの r/m フィールドが ESP を指しているか否かで決まる。 SIB バイトの中にはベースレジスタを決める base フィールドとインデックスレジスタを決める index フィールドが存在する。

x86 のメモリアドレスは (a, b, c) というタプルで指定できると考えられる。 a は ModeR/M の r/m フィールドで、b は SIB の base フィールド、c は SIB の index フィールドを指す。

a, b, c はそれぞれ 3 ビットなので 8 個のレジスタ(AX(0), CX(1), DX(2), BX(3), SP(4), BP(5), SI(6), DI(7)) を指定可能だ。 a が SP(4) 以外だったら後続の b と c の指定は無視される。 a が SP(4) だった場合、b がベースレジスタとして、c がスケール付きインデックスレジスタとして追加指定可能だ。

だが [ベースレジスタ + インデックスレジスタ * スケール] というフォーマットだと、インデックスレジスタだけを指定してベースレジスタを指定したくないというパターンがある。 例えば [EAX * スケール] だ。 この場合、もう一つの特殊ルールが発動する。 b に BP(5) を指定するとベースレジスタ指定が無視されるのだ。 つまり [EAX * スケール](SP(4), BP(5), AX(0)) と指定することになる。

ここから 64 ビット拡張の話

ところで AMD が 80386 (IA-32) を 64 ビット拡張する時に、汎用レジスタの数を 8 本から倍の 16 本に拡張した。 そのためレジスタを指定するフィールドが 1 ビット増えて 4 ビットになった。

この 64 ビット化時に命令フォーマットを大幅に変えればよかったのだが、AMD は REX と呼ばれる 1 バイトのプレフィックスをつけてやり過ごすと いう戦略を採った。 REX プレフィックの中にいくつかのビットフィールドがあり、その中の REX.B、REX.R、REX.X は既存の x86 命令のレジスタフィールドを補完する。

[R8] のように 1 レジスタ指定の場合、(a, b, c) の ModR/M の r/m フィードに RAX(0) を指定し REX.B に 1 を立てると、a に R8 を指定したと判断される。 つまり REX のビットが立っていると元のレジスタ番号に +8 される。

やや特殊なのは [R12] で、REX.B が 1 で ModR/M の r/m フィールドが RSP(4) を指定した場合は、32 ビットモードまでと同じく SIB 指定が有効になる。 その場合、REX.B は a ではなく次の b を修飾することになり、SIB の base フィールドと REX.B フィールドを合わせたものがベースレジスタ番号になる。 つまり [R12][RSP] と同様に ModR/M バイトだけではなく、SIB バイトを使ってメモリアドレスを指定する必要があるのだ。

資料を読むと疑問が深まる

ここで問題になるのは REX.B=1 で SIB バイトが base が 4 を指す、つまり R13 相当だった場合どうなるだろう? (SP(4), R13(5), AX(0))[RAX * スケール] なのだろうか? それとも [R13 + RAX * スケール] なのだろうか?

Intel の資料Intel64 and IA-32 Architectures Software Developer's Manual Volume 2A: Instruction Set Reference, A-M の 2-13 ページの表を見る。

  • 表の1行目の「ModR/M Byte が r/m == b*100(ESP)」の場合が SIB を追加指定の特例である。 REX.B の値によらず r/m が SP(4) なら SIB を拡張せよと読める。 「don't care」と括弧書きされて注釈が打ってある。
  • 表の4行目の「SIB Byte が base == 0101(EBP)」の場合がベースレジスタキャンセルの特例である。 赤い下線と紫の下線を見る限り REX.B が 1 の場合にどう解釈すればよいのか曖昧だ。

R13 でもベースレジスタキャンセルが効きそうな気がするが、だったら4行目の一番右の欄に「don't care」と書いてあってもよいと思われる。 1行目と4行目の記述の違いが疑心暗鬼に陥らせる。

一方、AMD の資料の AMD64 Architecture Programmer's Manual Volume 3: General-Purpose and System Instructions Rev 3.14の16ページによると、REX.B が 1 で SIB バイトの base が 5 の場合は、ベースレジスタキャンセルと明記されている。 こっちには「Don't care」って書いてあるじゃん。

Intel の資料は SIB バイトのベースレジスタキャンセルの特例の中に「REX.B は don't care」を書き忘れているのでは…


10/17 (土)

眼鏡が壊れた

昨日また眼鏡のフレームを壊してしまったよ。 就寝前に顔を洗おうと眼鏡に手を当てると稼動部分がぽっきりきたよ。 トホホ。

日記を見直すと同様に 2005年1月11日 2007年6月21日にフレームが壊れている。 1万円ぐらいの安いフレームは剛性が足らないのかしら。

とりあえず朝のうちに眼鏡を修理に出して夕刻に戻ってきたものの、 今日は予定が潰れてしまう。ナムナム。

[Food] ファイト餃子@庚申塚

大学生の頃によく行った ファイト餃子@庚申塚をまた食べたいと思い、 東京に出たときに庚申塚に寄ってみるが2回行って2回とも売り切れで店が閉まっていた。

今日は眼鏡が壊れてディスプレイに座る作業が出来ないので、 よい機会なのでリベンジに向かう。 ちなみに前回は行ったのは2004年9月6日なので 5年ぶりぐらいね。

お店は今日も繁盛。 店の前に人が並んでいるよ。 15個の餃子定食を食べるが、 大変懐かしい味に感無量。

西巣鴨でみかけた細いビル

西巣鴨で見かけたペンシルビル(手前)。 同系色だが後ろのマンションとは別の建物。

猫の額のような場所によく建てるよね。


10/12 (月)

[Food] ジャンボマッシュルームのハンバーガー

フレッシュネスバーガーで 「ベジタブルバーガー マッシュルーム」が発売されたので、 これを食べてみたよ。

写真のパテは普通のハンバーガーサイズで、 マッシュルームはその一回り小さい程度のサイズ。 味はやはり椎茸を思わせる。 マッシュルームの触感のでっかい椎茸バーガーです。

個人的にはそこそこ美味しいと思うが、 不味いと感じる人もいるだろね…

ちなみにジャンボマッシュルームを最後に食べたのは 2003年9月13日で、 この時は恵比寿の「マッシュルーム」というフレンチレストランで食べた。

コメントを書き込む
[1] [cola] 2009-10-15 22:02:21
お久しぶりです,colaです。

相変わらずグルメですな。

こっちに帰ったら,連絡してね^^
[2] [nminoru] 2009-10-18 00:06:16
お久しぶり。ご無沙汰しております。

最近は全然グルメじゃありませんよ。
会社と自宅の間をぐるぐる周るだけの日々が続いています。

機会があればまたお会いしましょう(^_^;

10/8 (木)

台風18号

久しぶりに大型の台風が接近中。


10/7 (水)

Google のロゴがバーコード

本日のGoogle のトップ画面はバーコード(ITmedia)になっていた。

帰宅後に 2004年8月30日に購入した バーコードリーダーで読み込んでみたらGoogleの文字が確認できたよ。


10/4 (日)

黄金の都シカン展@上野の国立科学博物館 (公式)

上野の国立科学博物館で開催されている「黄金の都シカン」展に行って来た。

シカンはペルーで750年から1350年頃に栄えた文明らしい。 今回の展示は日本人考古学者 南イリノイ大学 島田泉教授が長年取り組んでいるシカンの「ロロ遺跡」からの発掘物と、 その発掘事跡の紹介が中心だ。

ところでシカンの名前は今まで知らなんだが、 展示物には強烈に既視感があった。 部屋に帰った後に私が高校生の頃(1991年!)に山口県立美術館で見た「ペルー黄金博物館展」のカタログを見直してみたが、 そこには「シカン黄金製のトゥミ」(「ペルーの象徴 トゥミ」項の写真)が載っていた。

ただそこにはチムー文化と紹介され、 シカン神のモチーフは神像ではなく人物像だと記述されている。 この18年ぐらいでシカンに対する解釈が変化したんだろうね。

カタログの解説には 1988年からシパンを発掘する考古学者として島田泉の名前が上がっている。

P.S.

上野公園内を散策していると「国立西洋美術館を世界遺産へ」と書かれた のぼりが多数立っていた。


先月の日記(2009年09月) 今月の日記(2009年10月)
2002 | 10 | 11 | 12
2003 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2004 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2005 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2006 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2007 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2008 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2009 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2010 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2011 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2012 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2013 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2014 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2015 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2016 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2017 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2018 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2019 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2020 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2021 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2022 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2023 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
2024 | 1 | 2 | 3
ホームページ | 最新のコメント50
インデックス: 食べ歩き | Java | プログラム | UNIX | 画像
最新の日記へのリンク | この日記ページをはてなアンテナに追加 この日記ページをはてなブックマークに追加
はてな ダイアリー アンテナ ブックマーク ブログ
Twitter | mixi | Facebook | slideshare | github | Qiita


Written by NAKAMURA Minoru, Email: nminoru atmark nminoru dot jp, Twitter:@nminoru_jp