2016-07-10 8 views
0
.data 
.global _start 
_start: 
    mov r7, #4 
    mov r0, #1 
    mov r2, #12 
    ldr r4, =#0x6c6c6548 
    str r4, [pc, #4] 
    mov r1, pc 
    add pc, pc, #8 
    strbt r6, [ip], -r8, asr #10 
    svcvs 0x0057206f 
    beq 0x193b248 
    swi #0 
    mov r7, #1 
    mov r0, #0 
    swi #0 

この小さなARMアセンブリプログラムは、 "Hello World"を表示していました。テストにtest.sとして保存します。このアセンブリプログラムは "Hello World"をどのように印刷できますか?

$ as -o test.o test.s 
$ ld -o test test.o 
$ ./test 
Hello World 
$ 

どのようにこの仕事をしますか?私はプログラム全体で1つの文字列を見ることはできません。また、他の場所から文字列を読み取ることもありません。このコードは文字列を印刷するために必要なすべてのものです。文字列はどこから来たのですか?ここで

+0

ああ、そうです。私が正しくそれをしたら、それは "lleH"(これは後方ですか?)でなければなりません。残りはどこですか? 2番目の16進定数は0バイトを含み、3番目の定数はさらに奇妙に見えます。 – user6571836

答えて

0

が面白いビットの注釈です:

mov r7, #4 
    mov r0, #1 
    mov r2, #12 
    ldr r4, =#0x6c6c6548 
A str r4, [pc, #4] 
B mov r1, pc 
C add pc, pc, #8 
D strbt r6, [ip], -r8, asr #10 
E svcvs 0x0057206f 
F beq 0x193b248 
G swi #0 
    mov r7, #1 
    mov r0, #0 
    swi #0 

Aの店は場所Dを狙っている - コメントで指摘したように、その単語(リトルエンディアンの順序で)が作成した4 ASCIIは地獄」バイト" - それは無意味な命令の上に格納されます(そのマシンコードは0xe66c6548 - closeですが、十分ではありません)。おそらくこれがデータセクションにあり、書き込み可能であることを保証するための理由も考えられます*。一方、Eの命令のマシンコードは0x6f57206fであり、 "o Wo"となります。命令Fは、そのアドレスが "rld"のように見える符号化された相対分岐オフセットをもたらす必要があるため、特に扱いにくいです。** - beqエンコーディングは0x0annnnnnです.nnnnnnは26ビットの2の補数の上位24ビットですオフセット値 - トップバイトの条件コードとオペコードが最終改行を構成することにも注意してください。

命令Bは、Dというアドレスをr1に格納します。つまり、文字列の先頭を指すポインタです。 r0とr2は明らかに他の必要なsyscall引数であり、r7はシステムコール番号です(私はそれを調べるのが面倒ですが、r0の1はstdout、r2の12は文字数、システムコール4はwriteです)。

最後に、命令CGでシステムコールへのジャンプがあるのでDE、およびFで「命令」のどれもが、実際に(それ以降の残りはちょうどexitシステムコールをしている)が実行されていません。

トリックコードのためにかなりきちんとしています。

*また、データセクションを実行可能にするために、ローダーでいくつかの後方互換性の動作に依存していると思われます。

**おそらく私のbinutils 2.26リンカでは発生しません。おそらく、最近のバージョンではデフォルトセクションのアライメントが変更されているためです。

+0

待って、組み立てたときに説明書自体に文字列が含まれていると言っていますか?それはいいね。正しい文字列を生成するためにどのような命令を使う必要があるのか​​、彼らはどのように知っていますか?また、なぜインストラクションAは必要ですか?文字列の正しい部分を生成する別の命令を使うことができませんでしたか? – user6571836

+1

@ user6571836 ARMではこれが標準です。 「リテラルプール」(http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0473f/Bgbccbdi.html)が何であるか参照してください。コードフラグメントは、部分的に成功した逆アセンブリとなるようにシードします。 –

+0

@ user6571836命令符号化インデックスを調べることで、オペコードビットが必要なデータと一致するものを探し出し、残りのものに合わせてオペランドを作成したり、逆アセンブラを使って目的のデータを強制的に反転させて、 (どちらの場合でも不運な場合は、パッチを当てる方法を検討してください)。 0x6c6c6548_is_実際には有効な命令エンコーディングであることが判明しました。わかりやすく陳腐化したFPUにはいくつか狂ったニーモニックがありますが、本当に気にしていれば汎用のstc命令にデコードすることもできます。 – Notlikethat

関連する問題