val関数で符号なし32ビット変数No.31731
K2man さん 12/10/26 06:10
 
お世話になります。

マクロで、TCP/IP通信のダンプログからシーケンス番号を
抽出し、一覧表示させる処理を作成しているのですが、
シーケンス番号は32ビットの値で、ダンプから抜き出した値の
最上位ビットが立っている場合、val関数で数値化すると当然負の値になります。

これを符号なし32ビットの正の値として取得する方法が分かりません。特にval関
数を使用しなくても構いません。

なにか良い方法等ありましたら、ご教授頂けないでしょうか?



[ ]
RE:31731 val関数で符号なし32ビット変数No.31732
秀丸担当 さん 12/10/26 09:41
 

>これを符号なし32ビットの正の値として取得する方法が分かりません。特にval関
>数を使用しなくても構いません。
>
>なにか良い方法等ありましたら、ご教授頂けないでしょうか?

言われている通り、
val("0xffffffff")
というような場合、最上位ビットが立っていることでマイナスとして解釈されま
す。

1つの方法として、秀丸エディタの浮動小数点数バージョンを使うと、
setfloatmodeを使うことで、大きな数値も扱うことができるようする方法があり
ます。

 秀丸エディタ浮動小数点数バージョン
 http://hide.maruo.co.jp/software/hmfloat.html

例:
  setfloatmode 1;
  message str(val("0xffffffff"));

浮動小数点数バージョンであっても、setfloatmodeを使わなければマクロは通常
版と同じように互換性を保って-1を返すので、浮動小数点数を考慮していないマ
クロもそのまま使うことができます。

他の方法としては、数値化する目的にもよりますが、比較するだけであれば、桁
数を揃えると文字列をそのまま比較できると思います。
例えば、if("10">"f") はfalseですが、桁数を揃えてif("10">"0f")とすると
trueになります。

[ ]
RE:31732 val関数で符号なし32ビット変数No.31736
K2man さん 12/10/26 20:47
 
お返事の方ありがとうございます。

本マクロは他ユーザーにも使用して貰うつもりです。
浮動小数点バージョンを他ユーザーにインストールしてもらう
事は避けたいです。

比較もする必要はなく、単にダンプから抜いて数値化し、
テキスト出力するだけです。

通常版では不可能でしょうか?

であれば、マクロはあきらめてVC等でツールを作ります。

[ ]
RE:31736 val関数で符号なし32ビット変数No.31737
秀まるお2 さん 12/10/26 22:38
 
 作戦を考えてみたんですけども、まずはオーバーフローの気にないようにする
ために、文字列化された数値の足し算/引き算をするサブルーチンを別途用意し
ます。例えば"123"という文字列と"456"という文字列を、文字列のままで数値的
に足し算して、"579"って文字列を返すような、そういうサブルーチンを作りま
す。そういうのが1つあれば、あとはオーバーフローは気にしないで計算出来ま
す。

 それで、問題の数値ですが、問題の数値から0x80000000を引いてやればオー
バーフロー状態を脱するので、まずはそうしてやってかち文字列に変換し、そこ
からは文字列同士の足し算関数で、0x80000000を10進数化した"2147483648"を
足してやります。

 そうすると正しい値が出ます。

 サンプルマクロは以下の通りです。ちょっと長いですけども、サブルーチンと
しては、ConvertSpositiveValって関数に数値を渡してやって、結果が$$return
で返ってくるという、ただそれだけで使えます。


    //テスト
    #x = 0x7FFFFFFF;
    while(1) {
        call ConvertPositiveVal #x;
        question "0x" + hex(#x) + " == " + $$return;
        if( result != yes ) {
            break;
        }
        #x = #x + 1;
    }
    endmacro;


//こっちが目的のサブルーチン
ConvertPositiveVal:
    if( ##1 >= 0 ) {
        return str(#x);
    }
    ##positive = ##1 - 0x80000000;
    $$s1 = str(##positive);
    $$s2 = "2147483648";        //0x80000000を10進数表記する。
    call StringNumberAdd $$s1, $$s2;
    return $$return;

StringNumberAdd:
    ##len1 = strlen($$1);
    ##len2 = strlen($$2);
    $$result = "";
    ##x = 0;
    ##overflow = 0;
    while( ##x < ##len1 || ##x < ##len2 ) {
        if( ##len1 > ##x ) {
            ##digit1 = val( midstr( $$1, ##len1 - ##x - 1, 1 ) );
        } else {
            ##digit1 = 0;
        }
        if( ##len2 > ##x ) {
            ##digit2 = val( midstr( $$2, ##len2 - ##x - 1, 1 ) );
        } else {
            ##digit2 = 0;
        }
        ##sum = ##overflow + ##digit1 + ##digit2;
        ##overflow = ##sum / 10;
        ##sum = ##sum % 10;
        $$result = str(##sum) + $$result;
        ##x = ##x + 1;
    }
    if( ##overflow != 0 ) {
        $$result = str(##overflow) + $$result;
    }
    return $$result;

[ ]
RE:31737 val関数で符号なし32ビット変数No.31739
K2man さん 12/10/27 19:12
 
お世話になります。

どうもありがとうございます!!

この提示頂いたマクロを参考にさせて頂きます。


[ ]
RE:31737 val関数で符号なし32ビット変数No.31752
K2man さん 12/10/31 17:09
 
お世話になります。

結果報告ですが、思い通りの出力結果になりました。
ありがとうございました。

また、提示頂いたサブルーチンだけ使用したのですが、

//こっちが目的のサブルーチン
ConvertPositiveVal:
    if( ##1 >= 0 ) {
        return str(#x);
    }

の部分においての返り値は

 return str(##1);

とした方が他への依存が無いので良いですよね。
(当方のメインループでは#xに代入していないので、返り値が必ず"0"になり、あれ
れ?と思いました(笑))


[ ]
RE:31752 val関数で符号なし32ビット変数No.31753
秀まるお2 さん 12/10/31 17:40
 
> の部分においての返り値は
>
>  return str(##1);

 バグのご指摘ありがとうございます。間違ってたらまずいと思ってけっこう見
直したつもりでしたが、やはりバグを出してしまいました。失礼しました。

[ ]