<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>kamo from scratch</title>
    <link rel="alternate" type="text/html" href="http://labs.cybozu.co.jp/blog/kamoshida/" />
    <link rel="self" type="application/atom+xml" href="http://labs.cybozu.co.jp/blog/kamoshida/atom.xml" />
   <id>tag:labs.cybozu.co.jp,2008:/blog/kamoshida//12</id>
    <link rel="service.post" type="application/atom+xml" href="http://labs.cybozu.co.jp/cgi-bin/mt-admin/mt-atom.cgi/weblog/blog_id=12" title="kamo from scratch" />
    <updated>2008-03-17T06:27:37Z</updated>
    <subtitle>鴨志田 良和のブログ</subtitle>
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type</generator>
 
<entry>
    <title>Shibuya.abc#1</title>
    <link rel="alternate" type="text/html" href="http://labs.cybozu.co.jp/blog/kamoshida/2008/03/shibuyaabc1.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://labs.cybozu.co.jp/cgi-bin/mt-admin/mt-atom.cgi/weblog/blog_id=12/entry_id=1819" title="Shibuya.abc#1" />
    <id>tag:labs.cybozu.co.jp,2008:/blog/kamoshida//12.1819</id>
    
    <published>2008-03-15T08:11:30Z</published>
    <updated>2008-03-17T06:27:37Z</updated>
    
    <summary>3月15日に、サイボウズ・ラボのオフィスでShibuya.abc#1が開催されました。
私もFlashLiteむけSWFの最適化の話をお話しさせていただきました。
ABC(ActionScript Byte Code)に関連する濃い話をいろいろ聞けて楽しかったです。</summary>
    <author>
        <name></name>
        
    </author>
    
    <content type="html" xml:lang="ja" xml:base="http://labs.cybozu.co.jp/blog/kamoshida/">
        <![CDATA[しばらくさぼったままでしたが、久しぶりに更新します。

3月15日に、サイボウズ・ラボのオフィスでShibuya.abc#1が開催されました。
私もFlashLiteむけSWFの最適化の話をお話しさせていただきました。
ABC(ActionScript Byte Code)に関連する濃い話をいろいろ聞けて楽しかったです。

私の発表資料は、ここからダウンロードすることができます。
<a href="http://labs.cybozu.co.jp/blog/kamoshida/kamoshida20080315.pdf">ファイルをダウンロード</a>

勉強会の動画は、ニコニコ動画で見ることができるようです。西尾さん、ありがとうございます。
<a href="http://www.nicovideo.jp/mylist/5637933
">Shibuya.abc#1</a>

<div style="width:460px;border-style:solid;border-color:#ccc;border:1px;padding:0px;margin:0px auto;margin-bottom:10px;text-align:center;font-size:10px;"><iframe style="border-style:solid;border-color:#ccc;border-top:0px;border-right:0px;border-bottom:1px;border-left:0px;margin:0px;padding:0px;width:460px;height: 170px;" src="http://www.nicovideo.jp/thumb/sm2680989" title="Shibuya.abc#1_3" scrolling="no" frameborder="0"><a href="http://www.nicovideo.jp/watch/sm2680989">Shibuya.abc#1_3</a></iframe><br />この動画のダウンロード：<a title="ダウロードするには、対象の動画ページを表示させておく必要があります" href="http://smile-clb43.nicovideo.jp/smile?v=2680989.5674" rel="nofollow">一般</a>／<a title="エコノミーモード発動時はこちら" href="http://smile-clb43.nicovideo.jp/smile?v=2680989.5674low" rel="nofollow">エコノミー</a>／<a title="プレミアムアカウントの場合はこちら" href="http://smile-psu43.nicovideo.jp/smile?v=2680989.5674" rel="nofollow">プレミアム</a> Posted with <a href="http://aerith.mydns.jp/bin/nicodav/nicodavgen.html">NicodavGen</a> on 2008.03.17</div>


]]>
        
    </content>
</entry>
<entry>
    <title>Flash: コールスタック</title>
    <link rel="alternate" type="text/html" href="http://labs.cybozu.co.jp/blog/kamoshida/2007/07/flash_1.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://labs.cybozu.co.jp/cgi-bin/mt-admin/mt-atom.cgi/weblog/blog_id=12/entry_id=1396" title="Flash: コールスタック" />
    <id>tag:labs.cybozu.co.jp,2007:/blog/kamoshida//12.1396</id>
    
    <published>2007-07-12T08:42:00Z</published>
    <updated>2007-07-12T10:01:26Z</updated>
    
    <summary>FlashのVMはスタックマシンなので、たとえば演算をする場合は引数をスタックに...</summary>
    <author>
        <name></name>
        
    </author>
    
    <content type="html" xml:lang="ja" xml:base="http://labs.cybozu.co.jp/blog/kamoshida/">
        <![CDATA[FlashのVMはスタックマシンなので、たとえば演算をする場合は引数をスタックに積んでから演算命令を実行します。この用途で使われるスタック(ここでは値スタックと呼ぶことにしましょう)のほかにも、FlashのVM内で使われているスタックがあります。それは、Function CallやFrame Callをしたときに戻ってくる場所を保持しておく、コールスタックです。
<br/>
おなじ「スタック」ですが、VM内ではまったく別の場所で独立に管理されているようです。
ですから、コールする側が値をスタックに積んでおいて、コールされた側でその値を読み出したり、
逆に、コールされた側で値をスタックに積んで、Returnした後にその値を読み出す、といったことができます。
<br/>
以下を実行すると、
<pre style="border: 1px solid gray; margin: 0; padding: 0.5em; background-color: #eee;">
function foo () {
  __bytecode__("2696040000420003");
  // trace
  // push "B", undefined
  // pop
}

__bytecode__("96040000410003");
// push "A", undefined
// pop
foo()
__bytecode__("2696010003");
// trace
// push undefined
// pop
</pre>
画面に、
<pre style="border: 1px solid gray; margin: 0; padding: 0.5em; background-color: #eee;">
A
B
</pre>
が表示されます。foo()内のtraceで、呼び出す前に積んでおいたAが、
foo()から帰ってきた後のtraceでfoo()の中で積んでおいたBが使われます。
関数呼び出しではなく、フレーム呼び出しの場合にも、同様のことができます。
<br/>
上でちょっとわかりにくいのは、__bytecode__命令で毎回最後にundefined(0x03)をpush
しているところかもしれません。
__bytecode__は、x = __bytecode__("...")のようにひとつの値を返す関数のように扱われるので、
値を使わない場合は自動的にpopが挿入されてしまいます。
これによってスタックに積んだ値が捨てられてしまうことがないように、undefinedを
pushしているのです。
<br/>
関数呼び出しの引数や返り値の受け渡しには実際にこれと似たようなことが行われています。
ただし、引数についてはローカル変数へのバインドを行うところが違います。
<br/>
上に述べたことを応用すると、
フレーム呼び出しでも返り値の受け渡しをスタック経由で行える、ということになります。
ActionScriptの文法の枠からは外れてしまいますが。]]>
        
    </content>
</entry>
<entry>
    <title>FlashLite: バイトコードもいじってコードサイズを減らす</title>
    <link rel="alternate" type="text/html" href="http://labs.cybozu.co.jp/blog/kamoshida/2007/06/flashlite_3.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://labs.cybozu.co.jp/cgi-bin/mt-admin/mt-atom.cgi/weblog/blog_id=12/entry_id=1348" title="FlashLite: バイトコードもいじってコードサイズを減らす" />
    <id>tag:labs.cybozu.co.jp,2007:/blog/kamoshida//12.1348</id>
    
    <published>2007-06-15T09:17:49Z</published>
    <updated>2007-06-15T10:34:05Z</updated>
    
    <summary>コードサイズ節約ねたの続きです。 アクションスクリプトの工夫だけではどうにもなら...</summary>
    <author>
        <name></name>
        
    </author>
    
    <content type="html" xml:lang="ja" xml:base="http://labs.cybozu.co.jp/blog/kamoshida/">
        <![CDATA[コードサイズ節約ねたの続きです。
アクションスクリプトの工夫だけではどうにもならない場合に、SWFのバイトコードを書き換えるような最適化をすればさらにコードサイズを節約できることもあります。
SWFのバイトコードを書き換えるには、perlのSWF::Parserやflasmを使う方法があるようです。私はSWF::Parserに付属しているdumpswf.plxを使うことが多いです。

バイトコードを書き換えるような最適化には、たとえば以下のようなものがあります。

<h3>交換法則と<a href="http://labs.cybozu.co.jp/blog/kamoshida/2007/01/flash_push.html">まとめpush</a>のあわせ技</h3>
i + 2 よりも、2 + iのほうがまとめpushしやすくなります。<br/>

i = i + 2;の例です。
<pre style="border: 1px solid gray; margin: 0; padding: 0.5em; background-color: #eee;">最適化前(21 bytes):
                96 03 00 00 69 00 96 03 00 00 69 00
                1C 96 03 00 00 32 00 0A 1D
まとめpush適用(18 bytes):
                96 06 00 00 69 00 00 69 00 1C 96 03
                00 00 32 00 0A 1D
2+iとしてまとめpush(15 bytes):
                96 09 00 00 69 00 00 32 00 00 69 00
                1C 0A 1D</pre>

<h3>Increment/Decrementを使う</h3>
±3までなら、足し算・引き算は、+1、-1を行う命令を使うほうがお得です。
上のi = i + 2の例で、Increment命令(0x50)を使うと以下のように12 bytesになります。
<pre style="border: 1px solid gray; margin: 0; padding: 0.5em; background-color: #eee;">96 06 00 00 69 00 00 69 00 1C <font color="blue">50 50</font> 1D</pre>

<h3>Duplicateを使う</h3>
同じ文字がたくさん並んだ文字列を作りたいなら、スタックトップを複製するDuplicate命令(0x4C)が使える場合があります。
Aが123回連続する文字列をxに代入したいなら、このように書けます。
<pre style="border: 1px solid gray; margin: 0; padding: 0.5em; background-color: #eee;">96 09 00 00 78 00 <font color="red">00 41 41 41 41 00
4C 21 4C 21 4C 21 4C 21 4C 21</font> 96 08
00 00 31 00 00 31 32 33 00 15 1D</pre>
赤い部分でAが128文字続く文字列を作ってます。やっていることを、アクションスクリプトで無理やり書くとこんな感じです。
<pre style="border: 1px solid gray; margin: 0; padding: 0.5em; background-color: #eee;">
tmp4 = "AAAA";
tmp8 = tmp4 add tmp4;
tmp16 = tmp8 add tmp8;
tmp32 = tmp16 add tmp16;
tmp64 = tmp32 add tmp32;
x = substring(tmp64 add tmp64, 1, 123);</pre>

<h3>まとめ</h3>
スタックに値を積む処理は、値の長さが小さいとヘッダの部分が3バイトあるのが気になります。Increment, DecrementやDuplicateをうまく組み合わせて使うことで、スタックに値を積む回数を減らすことができるので、これがコードサイズの節約につながります。
]]>
        
    </content>
</entry>
<entry>
    <title>FlashLite: コードサイズが小さいActionScript</title>
    <link rel="alternate" type="text/html" href="http://labs.cybozu.co.jp/blog/kamoshida/2007/06/flashlite_actionscript.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://labs.cybozu.co.jp/cgi-bin/mt-admin/mt-atom.cgi/weblog/blog_id=12/entry_id=1314" title="FlashLite: コードサイズが小さいActionScript" />
    <id>tag:labs.cybozu.co.jp,2007:/blog/kamoshida//12.1314</id>
    
    <published>2007-06-03T06:18:40Z</published>
    <updated>2007-06-03T08:18:27Z</updated>
    
    <summary>FlashLiteのアプリを携帯端末で動かす場合、サイズの制約を満たすためにコー...</summary>
    <author>
        <name></name>
        
    </author>
    
    <content type="html" xml:lang="ja" xml:base="http://labs.cybozu.co.jp/blog/kamoshida/">
        <![CDATA[FlashLiteのアプリを携帯端末で動かす場合、サイズの制約を満たすためにコードサイズを節約することが必要になる場合があります。コードサイズを節約するために、アクションスクリプトではどんなことができるのでしょう。短い変数名を使うなどはもちろん効果がありますが、例えばこんなこともできます。

<h3>ordを使う</h3>

数値を代入する代わりに、ord(文字列)を使うことができる場合があります。たとえば、

<pre style="border: 1px solid gray; margin: 0; padding: 0.5em; background-color: #eee;">i = 100;</pre>

は、

<pre style="border: 1px solid gray; margin: 0; padding: 0.5em; background-color: #eee;">i = mbord("d");</pre>

と書いてもiに代入される値は同じになります。(dのASCIIコードは100です。)<br>
バイトコードで見てみると、

<pre style="border: 1px solid gray; margin: 0; padding: 0.5em; background-color: #eee;">
前者: 96 03 00 00 69 00 96 05 00 00 31 30 30 00 1d
後者: 96 03 00 00 69 00 96 03 00 00 64 00 36 1d
</pre>

と、後者の方がサイズが小さくなります。mbordでなくordでも原理的には同じことができるはずですが、Flash Professional 8ではコンパイル時にord("d")を展開して100にしてくれるようで、前者とおなじコードが生成されました。
3桁以上の場合に得をして、SJISの文字コードの関係で使えない範囲があるので、100-128,160-223,253-255の96種類の数値に対して有効です。あとかなり使える場合は少ないと思いますが、同様にしてSJISの漢字1文字を5ケタの整数と対応させることもできます。この場合は2バイト節約可能です。

<h3>最初の文字を取り出す</h3>
文字列から一部分を取り出すにはsubstring命令を使いますが、最初の1文字だけを取り出すのならよりサイズを節約できる方法があります。

<pre style="border: 1px solid gray; margin: 0; padding: 0.5em; background-color: #eee;">x = substring(s,1,1);</pre>

は、

<pre style="border: 1px solid gray; margin: 0; padding: 0.5em; background-color: #eee;">x = chr(ord(s));</pre>

と書くことができます。バイトコードにすると、この場合は11バイト短くなります。このようなことができるのは、ordは最初の1文字だけを対象にするからです。

<pre style="border: 1px solid gray; margin: 0; padding: 0.5em; background-color: #eee;">
前者: 96 03 00 00 78 00 96 03 00 00 73 00 1c
     96 03 00 00 31 00 96 03 00 00 31 00 15 1d
後者: 96 03 00 00 78 00 96 03 00 00 73 00 1c
     32 33 1d
</pre>

pushのまとめ効果を考慮に入れても8バイト短くなります。

<pre style="border: 1px solid gray; margin: 0; padding: 0.5em; background-color: #eee;">
前者: 96 06 00 00 78 00 00 73 00 1c
     96 06 00 00 31 00 00 31 00 15 1d
後者: 96 06 00 00 78 00 00 73 00 1c
     32 33 1d
</pre>

<h3>実はたくさん使える短い名前の変数</h3>
マニュアルによれば、「変数名には、英数字とドル記号 ($) のみを使用できます。変数名の先頭に数字は指定できません。」とあります。しかもFlashLiteの場合変数名の大文字小文字は区別されませんから、1文字の変数はa-zと$の27種類しか使えないということになります。
しかしこれはアクションスクリプトの文法上の制限で、実はもっとたくさんの1文字変数が使えます。

ちょっと復習になりますが、以下の2つの文は同じx1という変数に値を代入しています。これは配列エミュレートのために使われますね。
<pre style="border: 1px solid gray; margin: 0; padding: 0.5em; background-color: #eee;">
x1 = 12345;
eval("x" add 1) = 12345;
</pre>
数字を連結することは必ずしも必要なく、
<pre style="border: 1px solid gray; margin: 0; padding: 0.5em; background-color: #eee;">
x = 12345;
eval("x") = 12345;
</pre>
上の2文は全く等価なものです。
<pre style="border: 1px solid gray; margin: 0; padding: 0.5em; background-color: #eee;">
eval("x") = 12345;
trace(eval("x"));
</pre>
とすれば当然12345が出力されます。<br>
では、以下を実行したら何が起きるでしょう。
<pre style="border: 1px solid gray; margin: 0; padding: 0.5em; background-color: #eee;">
eval("1") = 12345;
trace(eval("1"));
</pre>
<br>
<br>
<br>
実はこれを実行しても12345が出力されます。1という変数に値が代入されたのです。当然1 = 12345;という書き方はできませんが、evalを使うことで空白文字でも"\n"でも変数名に使うことができます。1バイトの文字列として使える文字の数は195個ありますが、その中で大文字小文字の区別を考慮して、/, ., :は特別な意味に扱われそう(未調査)なので除外すると、全部で166個の1文字変数を使えることになります。

<h3>未定義の変数の活用</h3>
未定義の変数を参照すると空文字列が返されます。これは、数値としては0のように扱われます。
たとえば下の100から109までを出力するプログラムでは、
<pre style="border: 1px solid gray; margin: 0; padding: 0.5em; background-color: #eee;">
for(i=0;i<10;++i){
  trace(100 + i);
}
</pre>
iがそれまでに使われないのが明らかであれば最初のi=0の初期化は不要ということになります。

<h3>応用編</h3>
特殊な1文字変数と未定義の変数値についての知識を応用すると、以下のようなことが書けます。

<pre style="border: 1px solid gray; margin: 0; padding: 0.5em; background-color: #eee;">
普通のスクリプト(47バイト)
b = (x==y)?"Hello":"";

同じことをする別な書き方(40バイト)
eval(1) = "Hello";
b = eval(x==y);
</pre>

ただし、変数"0"は未定義であるとします。x==yは0または1になります。それをevalすることで変数"0"または変数"1"の値をbに代入しています。

<h3>注意点</h3>
FlashLiteでコードサイズを小さくするための工夫をいくつか紹介しましたが、これらを適用しても、条件によっては必ずしもコードサイズが減るわけではありません。<br>
また、ほぼ間違いなくコードが読みにくくなってしまうと思います。
]]>
        
    </content>
</entry>
<entry>
    <title>FlashLite: SWF で FizzBuzz ってみた</title>
    <link rel="alternate" type="text/html" href="http://labs.cybozu.co.jp/blog/kamoshida/2007/05/flashlite_swf_fizzbuzz.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://labs.cybozu.co.jp/cgi-bin/mt-admin/mt-atom.cgi/weblog/blog_id=12/entry_id=1307" title="FlashLite: SWF で FizzBuzz ってみた" />
    <id>tag:labs.cybozu.co.jp,2007:/blog/kamoshida//12.1307</id>
    
    <published>2007-05-30T04:41:02Z</published>
    <updated>2007-05-30T04:59:32Z</updated>
    
    <summary>同僚の竹迫さんがFlashLiteでFizzBuzz Golf(いかに短いサイズ...</summary>
    <author>
        <name></name>
        
    </author>
    
    <content type="html" xml:lang="ja" xml:base="http://labs.cybozu.co.jp/blog/kamoshida/">
        <![CDATA[同僚の竹迫さんがFlashLiteでFizzBuzz Golf(いかに短いサイズでFizzBuzzを書くか)をしていたので、私もチャレンジしてみました。

<a href="http://labs.cybozu.co.jp/blog/kamoshida/fizz195.swf">FlashLite1.1で195 byte</a> になりました。FlashLite1.1で200バイトを切るのは大変でしたが、ちょっとした面白いことを知りました。

たとえば、
X = 100; よりも X = ord("d"); の方が1バイトお得
とか、
最初の文字をとりだす時には、substring(s,1,1); よりも chr(ord(s)); の方がお得
とか。
これらはアクションスクリプトだけを見ているとよくわかりませんが、バイトコードを眺めていると気がつくものです。他にもいくつかあるのでこれから少しずつ紹介していこうと思います。
]]>
        
    </content>
</entry>
<entry>
    <title>Perl: オブジェクトのunbless</title>
    <link rel="alternate" type="text/html" href="http://labs.cybozu.co.jp/blog/kamoshida/2007/04/perl_unbless.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://labs.cybozu.co.jp/cgi-bin/mt-admin/mt-atom.cgi/weblog/blog_id=12/entry_id=1223" title="Perl: オブジェクトのunbless" />
    <id>tag:labs.cybozu.co.jp,2007:/blog/kamoshida//12.1223</id>
    
    <published>2007-04-20T08:33:33Z</published>
    <updated>2007-04-20T08:56:12Z</updated>
    
    <summary>perlのblessはオブジェクトにクラス名をマッピングする命令です。 my $...</summary>
    <author>
        <name></name>
        
    </author>
    
    <content type="html" xml:lang="ja" xml:base="http://labs.cybozu.co.jp/blog/kamoshida/">
        <![CDATA[perlのblessはオブジェクトにクラス名をマッピングする命令です。

<pre style="border: 1px solid gray; margin: 0; padding: 0.5em; background-color: #eee;">my $a = bless {}, "AA::BB::CC";
print ref($a), "\n";</pre>

を実行すると、AA::BB::CCが表示されます。

ほかの名前でblessし直すとその名前で古い対応関係が上書きされます。ではその対応関係を解除するにはどうすればよいのでしょう。bless $a, "HASH"などとすれば、ref関数の結果はblessする前と同じになりますが、依然としてblessされたままです。たとえば、Scalar::Utilのblessed命令を実行すると、blessされたままであることがわかります。

blessの解除を行うために、Data::Structure::Utilパッケージのunblessという命令が使えます。

<pre style="border: 1px solid gray; margin: 0; padding: 0.5em; background-color: #eee;">use Scalar::Util qw(blessed);
use Data::Structure::Util qw(unbless);
my $a = bless {}, "TEST";
unbless($a);
print "Hello\n" if blessed($a);</pre>

これを実行しても、Helloは表示されません。同じ用途で、Acme::Damnのdamnも使えます。

<pre style="border: 1px solid gray; margin: 0; padding: 0.5em; background-color: #eee;">use Scalar::Util qw(blessed);
use Acme::Damn qw(damn);
my $b = bless {}, "TEST";
damn($b);
print "Hello\n" if blessed($b);</pre>

これも、同じ結果になります。どちらも、ソースを見てみるとperlだけではこれは記述できなくて、xsのなかで、

<pre style="border: 1px solid gray; margin: 0; padding: 0.5em; background-color: #eee;">SvOBJECT_off(sv);</pre>

を実行しています。blessされたオブジェクトであることを表しているフラグを0にしているわけです。一旦blessしたオブジェクトに対して、そのblessを解除するのって、実はそんなに簡単なことではないんですね。
]]>
        
    </content>
</entry>
<entry>
    <title>FlashLite: 定数を変数に入れる基準</title>
    <link rel="alternate" type="text/html" href="http://labs.cybozu.co.jp/blog/kamoshida/2007/03/flashlite_2.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://labs.cybozu.co.jp/cgi-bin/mt-admin/mt-atom.cgi/weblog/blog_id=12/entry_id=1161" title="FlashLite: 定数を変数に入れる基準" />
    <id>tag:labs.cybozu.co.jp,2007:/blog/kamoshida//12.1161</id>
    
    <published>2007-03-26T01:30:12Z</published>
    <updated>2007-03-26T03:26:52Z</updated>
    
    <summary>Flashでは変数名や定数など、頻繁に使用する文字列はLookup Tableに...</summary>
    <author>
        <name></name>
        
    </author>
    
    <content type="html" xml:lang="ja" xml:base="http://labs.cybozu.co.jp/blog/kamoshida/">
        <![CDATA[Flashでは変数名や定数など、頻繁に使用する文字列はLookup Tableに入れてコードサイズを節約してくれますが、FlashLite1.xにはその機能がありません。ですので、頻繁に使う定数などは短い名前の変数に入れてしまう、ということを自分でやることでコードサイズの節約ができる場合があります。FL1では、数値のデータも文字列としてコンパイルされるため、65536とかを大量に使う人には役に立つかもしれません。

で、このエントリーでは、何回使ったらお得なのかというのを計算してみようと思います。

65536を参照するときは、SWFでは65536をスタックにプッシュするという処理にコンパイルされます。
<pre style="border: 1px solid gray; margin: 0; padding: 0.5em; background-color: #eee;">push [65536]</pre>
16進ダンプすると、以下の10バイトになります。
<pre style="border: 1px solid gray; margin: 0; padding: 0.5em; background-color: #eee;">96 07 00 00 36 35 35 33 36 00</pre>
65536の5文字 + 5バイトというわけです。

一方変数Aの値の参照は、以下の7バイトになります。
<pre style="border: 1px solid gray; margin: 0; padding: 0.5em; background-color: #eee;">push [A]<br/>getvar</pre>
<pre style="border: 1px solid gray; margin: 0; padding: 0.5em; background-color: #eee;">96 03 00 00 41 00 1C</pre>

また、A=65536の代入処理は、以下の17バイトになります。
<pre style="border: 1px solid gray; margin: 0; padding: 0.5em; background-color: #eee;">push [A]<br/>push [65536]<br/>setvar</pre>
<pre style="border: 1px solid gray; margin: 0; padding: 0.5em; background-color: #eee;">96 03 00 00 41 00 96 07 00 00 36 35 35 33 36 00 1D</pre>
これは、定数長5文字+12バイトです。

したがって、たとえば65536を10回使うとすると、定数のまま使うと10 x 10バイトで100バイト、変数Aに65536を代入してから使うと17バイト+10 x 7バイトで87バイトで、変数Aに代入するほうが13バイト少ないということになります。

もし、A=65536の代入を行うときに、Aと65536をまとめてpushしてよいことにすると、さらに3バイト節約になります。

一般に長さnの定数をk回使用するとき、1文字の変数に代入してから使うほうがバイトコードのサイズが小さくなる条件は、
12+n - (n + 5 - 7) x k < 0
である、ということになります。
これを整数kについて解くと、
minimum(k) = CEILING((13+n)/(n-2))
となります。ただし、CEILING(x)はxを下回らない最小の整数です。
(まとめプッシュありの場合はminimum(k) = CEILING((10+n)/(n-2)))

実際の値を入れて表にしてみました。65536ならn=5なので、6回以上使うならお得ということになります。

<center>
<table cellspacing="2" cellpadding="2">
<tr style="background-color: #eee;"><th>n</th><th>k(まとめpushなし)</th><th>k(まとめpushあり)</th></tr>
<tr style="background-color: #eee;"><td>3</td><td>16</td><td>13</td></tr>
<tr style="background-color: #eee;"><td>4</td><td>9</td><td>7</td></tr>
<tr style="background-color: #eee;"><td>5</td><td>6</td><td>5</td></tr>
<tr style="background-color: #eee;"><td>6</td><td>5</td><td>4</td></tr>
<tr style="background-color: #eee;"><td>7</td><td>4</td><td>4</td></tr>
<tr style="background-color: #eee;"><td>8</td><td>4</td><td>3</td></tr>
<tr style="background-color: #eee;"><td>9</td><td>4</td><td>3</td></tr>
<tr style="background-color: #eee;"><td>10	</td><td>3</td><td>3</td></tr>
<tr style="background-color: #eee;"><td>11	</td><td>3</td><td>3</td></tr>
<tr style="background-color: #eee;"><td>12	</td><td>3</td><td>3</td></tr>
<tr style="background-color: #eee;"><td>13	</td><td>3</td><td>3</td></tr>
<tr style="background-color: #eee;"><td>14	</td><td>3</td><td>2</td></tr>
<tr style="background-color: #eee;"><td>15	</td><td>3</td><td>2</td></tr>
<tr style="background-color: #eee;"><td>16	</td><td>3</td><td>2</td></tr>
<tr style="background-color: #eee;"><td>17	</td><td>2</td><td>2</td></tr>
</table>
</center>

また、剰余(%)演算に定数が含まれる場合、たとえば
<pre style="border: 1px solid gray; margin: 0; padding: 0.5em; background-color: #eee;">X = Y % 65536;</pre>は、
<pre style="border: 1px solid gray; margin: 0; padding: 0.5em; background-color: #eee;">X = Y - int(Y / 65536) * 65536;</pre>
に変換されてコンパイルされるので、定数が使用される回数は1回ではなく2回とカウントします。

剰余演算をたくさん使っているときなどで、予想以上にコードサイズが大きくなってしまった場合など、定数を変数に代入することによってコードサイズの削減効果が期待できそうです。
とはいっても、せいぜい数10バイト程度かもしれませんが。
]]>
        
    </content>
</entry>
<entry>
    <title>FlashLite: SHA1計算</title>
    <link rel="alternate" type="text/html" href="http://labs.cybozu.co.jp/blog/kamoshida/2007/02/flashlite_sha1.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://labs.cybozu.co.jp/cgi-bin/mt-admin/mt-atom.cgi/weblog/blog_id=12/entry_id=1116" title="FlashLite: SHA1計算" />
    <id>tag:labs.cybozu.co.jp,2007:/blog/kamoshida//12.1116</id>
    
    <published>2007-02-26T02:26:02Z</published>
    <updated>2007-02-26T02:53:57Z</updated>
    
    <summary>FlashLiteでgetURLをつかってブラウザを呼び出すときに、URLにMA...</summary>
    <author>
        <name></name>
        
    </author>
    
    <content type="html" xml:lang="ja" xml:base="http://labs.cybozu.co.jp/blog/kamoshida/">
        <![CDATA[FlashLiteでgetURLをつかってブラウザを呼び出すときに、URLにMACを追加したくなり、FL1.xで動くものはまだ見たこと無いので<a href="http://www.ietf.org/rfc/rfc3174.txt">RFC3174</a>のサンプルコードを参考にしてSHA1を計算するプログラムを作ってみました。
FL1.xでは符号なし32bit整数やビット演算の命令がないので、16進数の文字列表現を多倍長演算してます。and,or,xorなどはひと桁ずつ表引きです。ですから、かなり処理が遅くて、手元の携帯電話では"abc"をハッシュするのに6秒くらいかかってしまいました。
あまりに遅いのでSHA1は使わず自前のハッシュ関数を作ることにしましたが、工夫すればSHA1の計算ももう少し速くなりそうな気はします。なにかよいアイデアがあれば教えてください。

<a href="http://labs.cybozu.co.jp/blog/kamoshida/sha1compute.fla">ファイルをダウンロード</a>
]]>
        
    </content>
</entry>
<entry>
    <title>Flash: 文字列長</title>
    <link rel="alternate" type="text/html" href="http://labs.cybozu.co.jp/blog/kamoshida/2007/01/flash.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://labs.cybozu.co.jp/cgi-bin/mt-admin/mt-atom.cgi/weblog/blog_id=12/entry_id=1074" title="Flash: 文字列長" />
    <id>tag:labs.cybozu.co.jp,2007:/blog/kamoshida//12.1074</id>
    
    <published>2007-01-29T02:36:39Z</published>
    <updated>2007-01-29T02:54:48Z</updated>
    
    <summary>Flashのアクションスクリプトのソースコードの中に書ける文字列の最大長はいくつ...</summary>
    <author>
        <name></name>
        
    </author>
    
    <content type="html" xml:lang="ja" xml:base="http://labs.cybozu.co.jp/blog/kamoshida/">
        <![CDATA[Flashのアクションスクリプトのソースコードの中に書ける文字列の最大長はいくつでしょうか。
答えは、65533です。

これは、SWFでスタックに値をPushするときに指定できるデータ長がunsigned shortであることが主な理由だと思われます。
たとえば、以下のようなコードで、長さ3の文字列"ABC"をスタックに積むことができます。
<pre style="border: 1px solid gray; margin: 0; padding: 0.5em; background-color: #eee;">96 <font color="red">05 00</font> <font color="blue">00</font> 41 42 43 00</pre>
文字列長は3ですが、型情報(<font color="blue">00</font>:文字列)と区切り文字(最後の00)を含むのでPushするデータの長さは3+2=5になります(<font color="red">05 00</font>の部分)。
データ長に指定できる値は0xFFFF = 65535までですから、65535から2を引いた65533文字までがpush可能であるということになります。

これはあくまでSWFに直接書ける文字列の最大長と言うことであって、文字列の連結などを行えば、さらに長い文字列を扱うことはできます。
]]>
        
    </content>
</entry>
<entry>
    <title>Flash: 複数要素のPush</title>
    <link rel="alternate" type="text/html" href="http://labs.cybozu.co.jp/blog/kamoshida/2007/01/flash_push.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://labs.cybozu.co.jp/cgi-bin/mt-admin/mt-atom.cgi/weblog/blog_id=12/entry_id=1072" title="Flash: 複数要素のPush" />
    <id>tag:labs.cybozu.co.jp,2007:/blog/kamoshida//12.1072</id>
    
    <published>2007-01-28T14:04:49Z</published>
    <updated>2007-01-28T14:29:30Z</updated>
    
    <summary>Flashでは、スタックに値を入れるとき、複数の値を一度にPushすることができ...</summary>
    <author>
        <name></name>
        
    </author>
    
    <content type="html" xml:lang="ja" xml:base="http://labs.cybozu.co.jp/blog/kamoshida/">
        <![CDATA[Flashでは、スタックに値を入れるとき、複数の値を一度にPushすることができます。
たとえば、"1"と"2"を一度にPushする場合は次のようなアクションを書きます。

<pre style="border: 1px solid gray; margin: 0; padding: 0.5em; background-color: #eee;">96 <font color="red">06 00</font> <font color="blue">00</font> 31 00 <font color="blue">00</font> 32 00</pre>

最初の96はアクション"Push"を表しています。<br/>
次の<font color="red">06 00</font>は、Pushするデータの長さです。<br/>
青い<font color="blue">00</font>の部分はデータ型になっていて、この場合は文字列です。文字列は最後の00が区切りになっているので、この場合は、"1"と"2"という二つの文字列をPushすることになります。<br/>

ここで、上のようなPush命令を
<pre style="border: 1px solid gray; margin: 0; padding: 0.5em; background-color: #eee;">push "1", "2"</pre>
のように書くこととします。
<br/>

さて、複数要素を一度にpushした場合、スタック上にはどのようにデータが配置されるのでしょう。push "1", "2"は、
<table><tr><td>[1]</td><td><pre style="border: 1px solid gray; margin: 0; padding: 0.5em; background-color: #eee;">push "1"<br/>push "2"</pre></td></tr></table>
と、
<table><tr><td>[2]</td><td><pre style="border: 1px solid gray; margin: 0; padding: 0.5em; background-color: #eee;">push "2"<br/>push "1"</pre></td></tr></table>
のどちらと等価なのでしょうか。<br/>

これを調べるために、次のようなプログラムを書いてみました。
<pre style="border: 1px solid gray; margin: 0; padding: 0.5em; background-color: #eee;">push "a"
push "1", "2"
subtract
setvar
[96 03 00 00 61 00 96 06 00 00 31 00 00 32 00 0B 1D]
</pre>
これで、変数aの値が-1ならば[1]、1ならば[2]が正しいということになります。
<br/>
実行してみると、変数aの値は-1になり、[1]のほうと等価であることがわかります。SWFのスタックはメモリ中のアドレスの小さい方から大きい方へと伸びている(そういう実装の方が素直である)と考えることができそうです。<br/>

ちなみに、スタックの伸びる方向がわかったので、上のテストプログラムは、以下のようにさらに短く書くこともできます。
<pre style="border: 1px solid gray; margin: 0; padding: 0.5em; background-color: #eee;">push "a", "1", "2"
subtract
setvar
[96 09 00 00 61 00 00 31 00 00 32 00 0B 1D]
</pre>

]]>
        
    </content>
</entry>
<entry>
    <title>FlashLite: 剰余演算</title>
    <link rel="alternate" type="text/html" href="http://labs.cybozu.co.jp/blog/kamoshida/2007/01/flashlite_1.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://labs.cybozu.co.jp/cgi-bin/mt-admin/mt-atom.cgi/weblog/blog_id=12/entry_id=1070" title="FlashLite: 剰余演算" />
    <id>tag:labs.cybozu.co.jp,2007:/blog/kamoshida//12.1070</id>
    
    <published>2007-01-27T18:43:07Z</published>
    <updated>2007-01-27T18:57:38Z</updated>
    
    <summary>FlashLiteで使われているSWFバージョン4では、割り算の余りを求める命令...</summary>
    <author>
        <name></name>
        
    </author>
    
    <content type="html" xml:lang="ja" xml:base="http://labs.cybozu.co.jp/blog/kamoshida/">
        <![CDATA[FlashLiteで使われているSWFバージョン4では、割り算の余りを求める命令(C言語などで言う "%" 演算子)がないということを知りました。でも、ActionScriptの方には、"%" 演算子があるようです。そこで、"%"演算子を含む式がどのようなSWFに変換されるか調べてみました。
<pre style="border: 1px solid gray; margin: 0; padding: 0.5em; background-color: #eee;">b = a % c;</pre>
は、
<pre style="border: 1px solid gray; margin: 0; padding: 0.5em; background-color: #eee;">push "b"
push "a"
getvar
push "a"
getvar
push "c"
getvar
divide
intpart
push "c"
getvar
multiply
subtract
setvar
</pre>
のように変換されます。(SWFはスタックマシンです)
これは、
<pre style="border: 1px solid gray; margin: 0; padding: 0.5em; background-color: #eee;">b = a - int(a / c) * c;</pre>
というアクションスクリプトが変換されるSWFと全く同じものです。

"%" 演算子は、スクリプト上ではとても短いですが、実際には上のように結構長いコードに変換されてしまうので、サイズが気になる場合は使いすぎないように気をつけた方が良さそうです。

"%"に対応する命令が追加されるのは、SWFバージョン5からです。

]]>
        
    </content>
</entry>
<entry>
    <title>FlashLiteの数値について</title>
    <link rel="alternate" type="text/html" href="http://labs.cybozu.co.jp/blog/kamoshida/2007/01/flashlite.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://labs.cybozu.co.jp/cgi-bin/mt-admin/mt-atom.cgi/weblog/blog_id=12/entry_id=1048" title="FlashLiteの数値について" />
    <id>tag:labs.cybozu.co.jp,2007:/blog/kamoshida//12.1048</id>
    
    <published>2007-01-15T02:03:18Z</published>
    <updated>2007-01-15T03:35:46Z</updated>
    
    <summary>FlashとFlashLiteでは、使用されている数値の表現形式が違うようです。...</summary>
    <author>
        <name></name>
        
    </author>
    
    <content type="html" xml:lang="ja" xml:base="http://labs.cybozu.co.jp/blog/kamoshida/">
        FlashとFlashLiteでは、使用されている数値の表現形式が違うようです。

浮動小数点数の仮数部のビット数を求めるには、演算したときの桁落ちを利用します。
変数 v に2のn乗を代入して、別な変数 w に、 w = v + 1という代入をします。
ここで、w - vの値が0になればv + 1の計算が桁落ちしているので、仮数部はnビット以下ということになります。

この方法で調べると、Flashの仮数部は52ビットのようですので、おそらくIEEE754の倍精度浮動小数点数(符号部1ビット・指数部11ビット・仮数部52ビット)なのでしょう。PCで再生するならこれはとても普通です。

FlashLiteではFlashとは別の挙動を示します。
まず、1073741824(2^30です)に2をかけるとInfinityという文字列になります。符号付き32ビット整数っぽい結果です。

さらに、a = 999999999、 b = 0.00000001 としてa+bを計算すると、134217728.00000001が桁落ちなく計算されます。これは、IEEE754 doubleならば桁落ちしてしまう計算です。

2の-9乗は、0.001953125ですが、これは0.00195312と表示されます。9桁目の5が消えています。ただし、この値に2をかけると、正しく0.00390625が計算されます。表示はされませんが、内部的には9桁目を持っているようです。

32ビット整数で情報量を落とさずに表現できる10進数の桁数は9桁であることを考えると、FlashLiteでの数値の表現形式は、整数部と小数部で32ビットずつ使った固定小数点数であるように推測できます。
サイズは同じなのに、なぜ(Liteでない)Flashと同じように普通の倍精度浮動小数点数を使っていないのかはちょっとわかりません。

この手の仕様というのは、FlashLiteのインタプリタを作っている人は当然知っているはずですが、プログラマ向けには公開されていないものなのでしょうか。どなたかご存知の方がいらっしゃいましたら、教えてください。

        
    </content>
</entry>
<entry>
    <title>Flash Lite 1.xで使えない文字</title>
    <link rel="alternate" type="text/html" href="http://labs.cybozu.co.jp/blog/kamoshida/2007/01/flash_lite_1x.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://labs.cybozu.co.jp/cgi-bin/mt-admin/mt-atom.cgi/weblog/blog_id=12/entry_id=1035" title="Flash Lite 1.xで使えない文字" />
    <id>tag:labs.cybozu.co.jp,2007:/blog/kamoshida//12.1035</id>
    
    <published>2007-01-11T03:03:26Z</published>
    <updated>2007-01-26T01:08:47Z</updated>
    
    <summary>Flash Lite 1.xのアクションスクリプトでは、文字列に使用できない文字...</summary>
    <author>
        <name></name>
        
    </author>
    
    <content type="html" xml:lang="ja" xml:base="http://labs.cybozu.co.jp/blog/kamoshida/">
        <![CDATA[Flash Lite 1.xのアクションスクリプトでは、文字列に使用できない文字があります。

まず、\x00はSWFの中でデリミタとして使われているので使えません。

そのほかにも、正しいShift-JISの並びでないとFlashの開発環境(今使っているのは、Flash Pro 8 です)が望むようにコンパイルしてくれません。

たとえば、
<pre style="border: 1px solid gray; margin: 0; padding: 0.5em; background-color: #eee;">s = "abcdefghij";</pre>
のとき、
length(s) と ord(substring(s,4,1)) と ord(substring(s,5,1)) の値はそれぞれ10,100,101ですが、
<pre style="border: 1px solid gray; margin: 0; padding: 0.5em; background-color: #eee;">s = "abc\xffefghij";</pre>
の場合は先ほどの3つの値は、(9,101,102)となります。

つまり、Shift-JISとして無効な(\xff)が無視されてしまうのです。
本来なら、(10,255,101)になってほしいつもりでした。

バイナリ2.0カンファレンスのときの発表では、無効な文字より後がカットされてしまう(上の例なら3,0,0 となるはず)と話したのですが、年が明けて改めて試してみたら違う挙動になっていました。
試用期限が切れて製品版を購入してインストールしなおしたりしたので、そのあたりが関係しているのかもしれません。

また、2番目の例と等価なはずの
<pre style="border: 1px solid gray; margin: 0; padding: 0.5em; background-color: #eee;">s = "abc\xff\x65fghij";</pre>
の場合は、(8,102,103)になるし、
<pre style="border: 1px solid gray; margin: 0; padding: 0.5em; background-color: #eee;">s = "abc\377efghij";</pre>
の場合は、(10,121,101)となります。

121ってなんだろう。ちょっとだけ試してみましたが、\376は116、\375では同じ121になります。
これはあまり深追いしませんが、とにかく正しいShift-JISの並びを与える必要があるということです。

で、これはFlash Proのコンパイラのところの癖みたいなので、SWFを直接いじればたぶん大丈夫だろうということ(を口では言ってましたが試していなかったの)で試してみました。

最初の例の、s="abcdefghij"でSWFファイルを生成して、
<pre style="border: 1px solid gray; margin: 0; padding: 0.5em; background-color: #eee;">perl -ipe 's/abcdefg/abc\xff\x65fg/' test.swf</pre>
という変換をかけてから実行してみたところ、望みどおりの値(10,255,101)になりました。

というわけで、Flash Pro以外のツールを使ったり、Flash Proが生成したSWFをさらに変換したりすれば1バイトで255種類のパターンが扱えることになるので、文字列を圧縮データ格納に使いたい人(そんな人他にいないかもしれませんが)はもう少し圧縮率を稼ぐことができそうです。
]]>
        
    </content>
</entry>
<entry>
    <title>Binary 2.0 カンファレンス行ってきました</title>
    <link rel="alternate" type="text/html" href="http://labs.cybozu.co.jp/blog/kamoshida/2006/12/binary_20.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://labs.cybozu.co.jp/cgi-bin/mt-admin/mt-atom.cgi/weblog/blog_id=12/entry_id=981" title="Binary 2.0 カンファレンス行ってきました" />
    <id>tag:labs.cybozu.co.jp,2006:/blog/kamoshida//12.981</id>
    
    <published>2006-12-15T14:52:13Z</published>
    <updated>2007-01-04T06:29:55Z</updated>
    
    <summary>Binary 2.0カンファレンスに行って、LT枠でしゃべってきました。高林さん...</summary>
    <author>
        <name></name>
        
    </author>
    
    <content type="html" xml:lang="ja" xml:base="http://labs.cybozu.co.jp/blog/kamoshida/">
        <![CDATA[Binary 2.0カンファレンスに行って、LT枠でしゃべってきました。高林さんはじめ、スタッフの皆様お疲れ様でした。聞いてくださった方、ありがとうございました。私の話は、<a href="http://labs.cybozu.co.jp/blog/takesako/2006/12/pfi.html">竹迫さんのブログ</a>でも事前に紹介されていましたが、話題はFlash Liteで圧縮データを処理する方法についてでした。
本来は5分で話せる内容ではなくて、かなり駆け足になってしまってすみませんでした。
質問、コメント等あればこちらにお願いします。

<a href="http://labs.cybozu.co.jp/blog/kamoshida/061215b2con_kamoshida.pdf">発表資料(PDF:331,610バイト)</a>

]]>
        
    </content>
</entry>
<entry>
    <title>dd_rescueでバックアップ</title>
    <link rel="alternate" type="text/html" href="http://labs.cybozu.co.jp/blog/kamoshida/2006/11/dd_rescue_1.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://labs.cybozu.co.jp/cgi-bin/mt-admin/mt-atom.cgi/weblog/blog_id=12/entry_id=883" title="dd_rescueでバックアップ" />
    <id>tag:labs.cybozu.co.jp,2006:/blog/kamoshida//12.883</id>
    
    <published>2006-11-13T01:23:44Z</published>
    <updated>2007-01-04T06:29:53Z</updated>
    
    <summary>ディスクが壊れて、一部読み書きできないセクタがあるようなので、Linuxのdd_rescueを使ってバックアップをとることにしました。</summary>
    <author>
        <name></name>
        
    </author>
    
    <content type="html" xml:lang="ja" xml:base="http://labs.cybozu.co.jp/blog/kamoshida/">
        <![CDATA[社内の共有サーバのディスクが壊れて、一部読み書きできないセクタがあるようなので、注文した交換用のディスクが届くのを待つ間に、Linuxのdd_rescueを使ってバックアップをとることにしました。<br>
dd_rescueはディスクイメージをそのままコピーするddとほぼ同じ機能を持つコマンドで、とくにエラーが出る可能性があるディスクからデータを取り出すために、<br>
・エラーセクタがあっても、コピーを続行できる(これは、ddの<tt>conv=noerror</tt>オプションに相当する機能です)<br>
・ファイルの後ろから順にコピーすることができる<br>
・現在の進捗やエラーの発生回数の詳細な表示ができる<br>
などの機能が強化されているものです。<br>
<br>
たとえば、/dev/sdaの10Gバイト目から1Gバイト分のバックアップをとりたい場合は、次のようにします。<br>
<br>
<div id="code">
<tt>dd_rescue -A -m 1073741824 -s 10737418240 -S 0 /dev/sda backup_010.img</tt>
</div>
<br>
<tt>-A</tt> オプションは、エラーセクタ部分はゼロで埋める(ddの<tt>conv=sync</tt>に相当)<br>
<tt>-m</tt> オプションはコピーするサイズ<br>
<tt>-s</tt> オプションはコピー元の開始位置<br>
<tt>-S</tt> オプションはコピー先の開始位置<br>
<br>
です。<tt>-S</tt>は省略すると<tt>-s</tt>と同じ値になります。したがって、上の例のように、ファイルにバックアップする際には <tt>-S 0</tt> が必要になることが多いと思います。<br>
<br>
サイズや開始位置には、<tt>b</tt>(=512 ブロックサイズ)、<tt>k</tt>(=1024)、<tt>M</tt>(=1048576)、<tt>G</tt>(=1073741824)の単位をつけることができますので、以下のように書いても同じ動作をします。<br>
<br>
<div id="code">
<tt>dd_rescue -A -m 1G -s 10G -S 0 /dev/sda backup_010.img</tt>
</div>
<br>
また、逆向きコピーの場合は、<tt>-r</tt> オプションを使って、以下のように書きます。<br>
<br>
<div id="code">
<tt>dd_rescue <strong>-r</strong> -A -m 1G -s <strong>11G</strong> -S <strong>1G</strong> /dev/sda backup_010.img</tt>
</div>
<br>
注意しないといけないのは、<tt>-s, -S</tt>の値も変わることです。<br>
<br>
以下の2つのコマンドを実行した結果は同じものになります。<br>
<br>
<div id="code">
<tt>
dd_rescue -A    -m $size -s $spos  -S $dpos  $sfile $dfile
<br>
dd_rescue -A -r -m $size -s $spos2 -S $dpos2 $sfile $dfile
</tt>
<br>
ただし、 <tt>$spos2 = $spos + $size</tt><br>
  かつ、 <tt>$dpos2 = $dpos + $size</tt>
</div>
<br>
あと、今回使ってみて便利だなと思ったのは、<br>
・入出力をリダイレクトできる<br>
ことです。ファイル名のところに、- を指定することができます。ddだとこれができません。<br>
<br>
今回は、バックアップ先がwindows(smbmountしているディスク)で、空き容量もバックアップ元をすべてそのままおけるほど十分には残っていなかったので、<br>
・元のイメージは1Gバイトごとに分割(2GまでOKだと思いますが、後で数えやすそうなので1Gにしました)<br>
・それぞれの分割ファイルはgzipで圧縮<br>
することにしました。<br>
<br>
バックアップスクリプトは大体こんな感じです。<br>
<div id="code">
<pre>
for i in `seq 0 160`
do
  f=`printf backup_sda_%03d $i`
  echo $f
  dd_rescue -A -m 1G -s ${i}G -S 0 /dev/sda - | gzip -c > $f.gz
done
</pre>
</div>
リストア用はこれ。<br>
<div id="code">
<pre>
for i in `seq 0 160`
do
  f=`printf backup_sda_%03d $i`
  echo $f
  zcat $f.gz | dd_rescue -S ${i}G - /dev/sda
done
</pre>
</div>
たまに、dd_rescueがハングしてしまった時があったので、その部分は、<tt>-r</tt> オプションなども使って手作業でバックアップファイルをつくりました。<br>
]]>
        
    </content>
</entry>

</feed> 


