アカウント名:
パスワード:
いや、最終版に落ちるの早すぎ。もっと努力せよ。
str2num macro string:REQK/ecode>というこれを<ecode>str2num macro string:REQ, base:=10K/ecode>と書き直す。その上で<ecode> ; resに10をかける mov eax, res mov ebx, 10
という部分を
; resに 底 をかける mov eax, res mov ebx, base
.RADIX は値を設定したり開放したりが面倒ですよね。いままでn進数だったのを一時的に16進数でチェックして、再びn進数に戻す…なんてことができない。
そのニーズが出た段階で、私はcygwin の m4 + as + gcc -mingw に逃げてしまいます(^^;)。# MASM より古いけれど、m4 の方がマクロとして高機能。# m4 があるなら MASMよりも「マクロ機能のない」asの方が快適。
うーわー、面倒な質問を初心者の日記で…。
以下の説明に出てくる文法の多くは MASM には存在しない文法です。という注意書きを最初に書かなくちゃいけないじゃないか。
というわけで、MASMにはない文法のお話。MASMでは実装できません。
.
たとえば。Express_RADIX()という命令があるとしましょう。Express_RADIX(val, base)のように使い、val は「数値表現」、base は基数を『現在の基数で』表したものとします。# つまり val はマクロにとっては文字列であって、『現在の基数』の影響を受けない。
compare_2_order macro val:REQ, base:=<10> .IF val < Express_RADIX( 100, base ) xxxx .ENDIFendm
と書けます。この場合「100」の部分はまさに「100」でいい。10進数の100ではなく、「まさに100base」との比較をしていると表現できる。
もちろん、Express_RADIX なんかなくても似たようなことは出来て、
compare_2_order macro val:REQ base:=<10> .IF val < ( base * base ) xxxx .ENDIFendm
と書けばよい。普通のプログラマなら、「これで良いじゃん、十分分かるよ」と言うでしょう。
でも、そもそも「マクロ」というのは、as のような「.obj (あー、本当は .o なんだけどまぁ、いいよね)」の内容と1対1に対応するコマンドしか書けないアセンブラだけじゃ、書いていて辛いから発生したわけで。「なんとなく意味が通じる」じゃなく、「言いたいことが言いたい様に表現できる」のが本来あるべきだと思うんですよ。しかも、マクロのように「入れ子」になった表現において、入れ子になったもの同士が互いに悪影響を与えないように適切なカプセル化をするべきだと。
MASMは「マクロ」アセンブラとして不適切だ、という議論が大昔あったのですが、その理由のひとつがこの「マクロ同士がカプセル化できない命令体系」にあったと記憶しています。で、その最大の問題点は、変更した値を「前の値」に戻すための push/pop 機能がほとんどない、という点だったかと。
あとどれがMASMで実装できない文法なのか、私には良く分からなかったのですが、どこでしょうか?
Express_RADIX マクロ関数も普通に MASM で書けますしね…
因みにマクロの中に .RADIX を使っても書けますよ。
ただ、現在進数の数値を10進文字列に変換するマクロ関数はもしかしたら別に書かなければいけないかもしません。
マクロの中で .RADIX を変更して、元に戻す方法ですが、
Express_RADIX MACRO val:REQ, base:REQ LOCAL old_radix old_radix = 10 .RADIX 10 ; 例えば10進に変更する ; ... 何かの記述 .RADIX old_radixENDM
これで出来ます。まあ、私はあまりやりたくない方法ですけど。
連投スイマセン、補足です。
MASM の .RADIX は10進で値を与えなければならないのですが、例えば
.RADIX 16; ... 何かの記述.RADIX old_radix
でもちゃんと動作します。(これは確認済み)
old_radix が数値定数だからです。(テキストマクロでは多分無理だと思います)
度々連投すいません。投稿した後に、ふと思い出して調べましたら、PUSHCONTEXT/POPCONTEXT で RADIX も処理できるみたいです。(普段、ASSUMES しか使わないのでぼけてました)
と言うわけで、(#1854912) [srad.jp]のExpress_RADIXマクロ関数は、
Express_RADIX MACRO val:REQ, base:REQ LOCAL base_num, result_num PUSHCONTEXT RADIX base_num = base .RADIX base_num result_num = val POPCONTEXT RADIX EXITM %result_numENDM
で、val 数値文字列を、base(現在の RADIX 表現)基底で評価した値を、現在の .RADIX での数値表現した文字列に変換できます。記述も
とまったく同じに記述できて、これを使用したときの挙動も okky 氏の解説通りになると思います。マクロの入れ子の問題もありません。
このマクロが動かない例: おれ、このマクロを呼ぶ前は7進数で数字を表現してたんだ。 このマクロを呼んだら、それ以降が10進数になっちゃったよ。
# Express_RADIX を呼ぶ前の RADIX が「十」であるなどという保証はどこにも無い。
より多くのコメントがこの議論にあるかもしれませんが、JavaScriptが有効ではない環境を使用している場合、クラシックなコメントシステム(D1)に設定を変更する必要があります。
Stableって古いって意味だっけ? -- Debian初級
何故それが最終版… (スコア:1)
いや、最終版に落ちるの早すぎ。もっと努力せよ。
という部分を
fjの教祖様
Re: (スコア:1)
str2num macro string:REQ, base:=<10>
じゃないとダメかも。
もしかしたら、バージョンによってエラーは出ないのかもしれませんが、とりあえず<>で囲んでおいたほうが良いかと。
>実は MASM で base が 2,3,4,5,6,7,8,9,10 のどれかであることをチェックするのは意外と面倒なので省略。
あまり気にしたこと無いけど、10 で進数取れませんかね?
.IF eax >= 10
と書くと、eax が現在の .RADIX で一桁で表現できる数値の範囲外か判定できるかと。
(ただ、ASSUME eax:SDWORD されていると (DWORD PTR eax) >= 10 と書かないとダメですが)
Re: (スコア:1)
.RADIX は値を設定したり開放したりが面倒ですよね。
いままでn進数だったのを一時的に16進数でチェックして、再びn進数に戻す…なんてことができない。
そのニーズが出た段階で、私はcygwin の m4 + as + gcc -mingw に逃げてしまいます(^^;)。
# MASM より古いけれど、m4 の方がマクロとして高機能。
# m4 があるなら MASMよりも「マクロ機能のない」asの方が快適。
fjの教祖様
Re: (スコア:1)
そもそも、.RADIX を変更するシーンってどういうものですか?
Re:何故それが最終版… (スコア:1)
うーわー、面倒な質問を初心者の日記で…。
以下の説明に出てくる文法の多くは MASM には存在しない文法です。
という注意書きを最初に書かなくちゃいけないじゃないか。
というわけで、MASMにはない文法のお話。MASMでは実装できません。
.
たとえば。Express_RADIX()という命令があるとしましょう。Express_RADIX(val, base)のように使い、val は「数値表現」、base は基数を『現在の基数で』表したものとします。
# つまり val はマクロにとっては文字列であって、『現在の基数』の影響を受けない。
と書けます。この場合「100」の部分はまさに「100」でいい。10進数の100ではなく、「まさに100base」との比較をしていると表現できる。
.
もちろん、Express_RADIX なんかなくても似たようなことは出来て、
と書けばよい。普通のプログラマなら、「これで良いじゃん、十分分かるよ」と言うでしょう。
でも、そもそも「マクロ」というのは、as のような「.obj (あー、本当は .o なんだけどまぁ、いいよね)」の内容と1対1に対応するコマンドしか書けないアセンブラだけじゃ、書いていて辛いから発生したわけで。「なんとなく意味が通じる」じゃなく、「言いたいことが言いたい様に表現できる」のが本来あるべきだと思うんですよ。しかも、マクロのように「入れ子」になった表現において、入れ子になったもの同士が互いに悪影響を与えないように適切なカプセル化をするべきだと。
MASMは「マクロ」アセンブラとして不適切だ、という議論が大昔あったのですが、その理由のひとつがこの
「マクロ同士がカプセル化できない命令体系」
にあったと記憶しています。で、その最大の問題点は、変更した値を「前の値」に戻すための push/pop 機能がほとんどない、という点だったかと。
fjの教祖様
Re:何故それが最終版… (スコア:1)
それに .RADIX で変更しなくても、特定数字列を任意真数の数値に変換するマクロを書けば良いし、そんなのとても簡単ですよ?
それをわざわざ不適合な記法の例で MASM はだめだというのなら、他の言語だって同じですよね?
Re:何故それが最終版… (スコア:1)
あとどれがMASMで実装できない文法なのか、私には良く分からなかったのですが、どこでしょうか?
Express_RADIX マクロ関数も普通に MASM で書けますしね…
因みにマクロの中に .RADIX を使っても書けますよ。
ただ、現在進数の数値を10進文字列に変換するマクロ関数はもしかしたら別に書かなければいけないかもしません。
マクロの中で .RADIX を変更して、元に戻す方法ですが、
Express_RADIX MACRO val:REQ, base:REQ
LOCAL old_radix
old_radix = 10
.RADIX 10 ; 例えば10進に変更する
; ... 何かの記述
.RADIX old_radix
ENDM
これで出来ます。
まあ、私はあまりやりたくない方法ですけど。
Re:何故それが最終版… (スコア:1)
連投スイマセン、補足です。
MASM の .RADIX は10進で値を与えなければならないのですが、例えば
でもちゃんと動作します。(これは確認済み)
old_radix が数値定数だからです。(テキストマクロでは多分無理だと思います)
Re:何故それが最終版… (スコア:1)
度々連投すいません。
投稿した後に、ふと思い出して調べましたら、PUSHCONTEXT/POPCONTEXT で RADIX も処理できるみたいです。
(普段、ASSUMES しか使わないのでぼけてました)
と言うわけで、(#1854912) [srad.jp]のExpress_RADIXマクロ関数は、
Express_RADIX MACRO val:REQ, base:REQ
LOCAL base_num, result_num
PUSHCONTEXT RADIX
base_num = base
.RADIX base_num
result_num = val
POPCONTEXT RADIX
EXITM %result_num
ENDM
で、val 数値文字列を、base(現在の RADIX 表現)基底で評価した値を、現在の .RADIX での数値表現した文字列に変換できます。
記述も
とまったく同じに記述できて、これを使用したときの挙動も okky 氏の解説通りになると思います。
マクロの入れ子の問題もありません。
Re:何故それが最終版… (スコア:1)
このマクロが動かない例:
おれ、このマクロを呼ぶ前は7進数で数字を表現してたんだ。
このマクロを呼んだら、それ以降が10進数になっちゃったよ。
# Express_RADIX を呼ぶ前の RADIX が「十」であるなどという保証はどこにも無い。
fjの教祖様
Re:何故それが最終版… (スコア:1)
>このマクロを呼んだら、それ以降が10進数になっちゃったよ。
だから、元に戻りますって。
old_radix = 10
では old_radix を数値定数として、マクロが展開された時点の .RADIX での「10」(つまり7進数なら7)が old_radix に代入されます。(マクロの中身は展開されるまでテキストです)
そしてマクロが終わる前の
.RADIX old_radix
では、正しく以前の .RADIX に戻ります。
これは実際に別さまざまな .RADIX に変更して試しているので間違いありません。