str_replace()はわからないけど、
count()は配列の要素数を表すものであり
文字数を数えるものではないので
1度しかループしないように思うのですが・・・

もしそうであればcount()をstrlen()に変えればOK

で、%Xは数値→16進数の変換なので非数値は当然0になる。
文字をアスキーコードに変換したいのならord()を使いましょう。