1

たとえば、Assembly x86 では、.data エントリ セクションを使用して、次のようにデータ バイトを静的に定義できます。

MSG db 'CAGA', AAFF

私の質問は、フラット バイナリ (bin) ファイルにアセンブルしていると仮定して、バイナリ ファイルにデータを挿入するためにアセンブラがどのように、または何を行うかに関するものです。

私は逆コンパイルを試みているので知りたいのですが、機械語プログラミングの操作方法についても理解を深めたいと思っています。

システムソフトウェアをマシンコードでコーディングしたいのですが、アセンブラーはいくつかのマシンコードの概念 (静的データ宣言、アラインメント、命令幅、ステートメントの構造化、オペランド、またはコード全般など) を抽象化し、行き詰まっています。

私は単純に、マシン コードに関して、これらの基本事項の中でどのように配置されているかを尋ねています。

プログラムの .data 部分はどのようにファイルに静的に追加され、CPU が命令をフェッチするときにランタイム/処理時間でどのように使用されるのでしょうか? たとえば、次のプログラムでは、FASM 上の Intel 構文アセンブリ コードの x86 ブートローダーであり、

    [BITS 16]   ;Tells the assembler that its a 16 bit code
[ORG 0x7C00]    ;Origin, tell the assembler that where the code will
                ;be in memory after it is been loaded

MOV SI, HelloString ;Store string pointer to SI
CALL PrintString    ;Call print string procedure
JMP $       ;Infinite loop, hang it here.


PrintCharacter: ;Procedure to print character on screen
    ;Assume that ASCII value is in register AL
MOV AH, 0x0E    ;Tell BIOS that we need to print one charater on screen.
MOV BH, 0x00    ;Page no.
MOV BL, 0x07    ;Text attribute 0x07 is lightgrey font on black background

INT 0x10    ;Call video interrupt
RET     ;Return to calling procedure



PrintString:    ;Procedure to print string on screen
    ;Assume that string starting pointer is in register SI

next_character: ;Lable to fetch next character from string
MOV AL, [SI]    ;Get a byte from string and store in AL register
INC SI      ;Increment SI pointer
OR AL, AL   ;Check if value in AL is zero (end of string)
JZ exit_function ;If end then return
CALL PrintCharacter ;Else print the character which is in AL register
JMP next_character  ;Fetch next character from string
exit_function:  ;End label
RET     ;Return from procedure


;Data
HelloString db 'Hello World', 0 ;HelloWorld string ending with 0

TIMES 510 - ($ - $$) db 0   ;Fill the rest of sector with 0
DW 0xAA55           ;Add boot signature at the end of bootloader

" HelloString db 'Hello World', 0 " は 0 と 1 として bin ファイルに静的に挿入されますが、マシン コードでは、文字列ポインターを格納することにより、静的バイナリ データが MOV SI 命令のオペランドとしてどのように追加されるのでしょうか。登記簿上の住所?

基本的に、ファイル内のスタティック バイナリ データ バイトをコード オペランドとして実行し、ソース インデックス レジスタに移動するにはどうすればよいでしょうか?

4

2 に答える 2

0

あなたの質問への答えは、バイナリ ファイルの実行方法によって少し異なります。

Linux や MS-windows のようなオペレーティング システムが使用されていると仮定すると、バイナリ ファイルはヘッダー情報などで複雑になります。それを無視して、プログラムがメモリに格納されたら、それがどのように見えるかに集中しましょう。

少しシンプルです。

コードエリア

コードプレリュード

MOV AL,BL ...

コード後奏

データエリア

MYDATA: データ "caga",0AH

領域は伝統的にセグメントと呼ばれます。現在、その名前は Intel によってハイジャックされ、Microsoft や Linux (ELF) によってセクションと呼ばれています。しかし、強い関係があります。MOV はプログラムの開始場所ですが、セットアップのプレリュードとポストリュードが必要です (そうしないと、二度と Linux に戻ることはありません)。Pentium 上の典型的な Linux/Windows の状況では、セクションが Intel セグメント ハードウェアによってサポートされていることがわかります。つまり、MYDATA にジャンプすることはできません。つまり、MYDATA を含むようにプログラム カウンターを設定することはできません。代わりに、ハードウェアは、Linux では「セグメンテーション フォールト」を、Windows ではおそらくブルー スクリーンを処理します。

確かに、「データ」を実行できます。実際、コードは、実行するのに適切な場所と時間にあるデータにすぎないからです。たとえば、次のような行を入れることで、以下を強制的に実行可能にすることができます SECTION .text

(ばかげています、私は知っています。私はこれを作り上げていません。)

アセンブラ プログラム コード セクション MOV AL,BL では、0x88 と 0xD8 を 2 バイト連続してコード セグメントに入れることができます。入れても同じ効果が得られる

DB 0x88, 0xD8

プログラムのまったく同じ場所に。

上記が非常に単純化されていることがわかります。たとえば、典型的な ELF バイナリには、簡単に 20 のセクションを含めることができます。これもインテルにとってはやや特殊ですが、抽象よりも具体的な方が理解しやすいです。

あなたの例は明らかに起動状況です。HelloString が欠落しているため、完全ではありません。これをプログラムの最後に追加すると、HelloString はアドレス、つまり数値として記憶されます。MOV SI,.. 命令のアセンブル中に、その番号を埋めるための穴が残されました。ファイル全体を 1 回処理した後、HelloString アドレスが認識され、アセンブラがそれを埋めます。

グロッチェス・アルバート

于 2013-12-02T17:11:59.123 に答える