qsortのcallback関数
http://d.hatena.ne.jp/shinichiro_h/20070123#1169557406
に触発されてPPCで同じ事をやってみました。
int a[] = {1, 3, 7, 2, 6, 5, 4, 9, 8}; int main(){ int i; qsort(a, sizeof(a)/4, 4, "}#@\x2e}D@\x2e|jHPN\x80\0 "); for(i = 0; i < sizeof(a)/4; ++i){ printf("%d ", a[i]); } puts(""); return 0; }
これでちゃんと動いた。やっぱり文字列が長くなってしまうのはしょうがないのだけど、これでもちょっと工夫して短くしました。
まず、元のCのコードは
int cmp(int* a, int* b){ return *a - *b; }
lwz r5, 0(r3) lwz r6, 0(r4) sub r3, r5, r6 blr
軽く説明すると渡された引数は順番にr3, r4, r5, r6...とr3から順番にレジスタに入っていきます。戻り値はr3にいれて返します。
r3 〜 r10までが関数内で汎用的に使えるレジスタです。
PPCの場合メモリの中身を直接演算できないんで一旦読み出します。
雰囲気的には上のコードは
r5 = *(r3 + 0); r6 = *(r4 + 0); r3 = r5 - r6; return
みたいな感じ。
それで上のコードをそのまま機械語に直すとlwz命令の箇所が\x80\xa3\x00\x00\x80\xc4\x00\x00みたいになっちゃうんで、
lwzx r9, r3, r8 lwzx r10, r4, r8 sub r3, r9, r10 blr
と変更したものの機械語を使いました。
lwzxはr9 = *(r3 + r8)みたいな意味で、r8が0に初期化されることを利用してます。