len: equ 2
len: db 2
それらは同じで、代わりに使用できるラベルを作成してい2
ますか? そうでない場合、各申告書の長所と短所は何ですか? それらは同じ意味で使用できますか?
len: equ 2
len: db 2
それらは同じで、代わりに使用できるラベルを作成してい2
ますか? そうでない場合、各申告書の長所と短所は何ですか? それらは同じ意味で使用できますか?
1 つ目はequate
で、C に似ています。
#define len 2
最終的なコードで実際にスペースを割り当てないという点で、len
シンボルを 2 に設定するだけです。その後、len
後でソース コードで を使用すると、定数 を使用している場合と同じになります2
。
2 番目はdefine byte
で、C に似ています。
int len = 2;
実際には、メモリに1バイトのスペースを割り当て、そこにaを格納し、そのバイト2
のアドレスlen
に設定します。
違いを示す疑似アセンブラ コードを次に示します。
line addr code label instruction
---- ---- -------- ----- -----------
1 0000 org 1234h
2 1234 elen equ 2
3 1234 02 dlen db 2
4 1235 44 02 00 mov ax, elen
5 1238 44 34 12 mov ax, dlen
1 行目では、アセンブリ アドレスを に設定するだけで、1234h
何が起こっているのかを簡単に説明できます。
2 行目では、コードは生成されず、アセンブラーは単純elen
に値をシンボル テーブルにロードします2
。コードは生成されていないため、アドレスは変更されません。
次に、4 行目で使用すると、その値がレジスタにロードされます。
行 3 は、db
これが異なることを示しています。実際には、スペース (1 バイト) を割り当て、そのスペースに値を格納しています。その後、シンボル テーブルにロードされますが、定数値ではなく、dlen
そのアドレスの値が与えられます。1234h
2
後でdlen
5 行目で使用すると、実際の値を取得するために逆参照する必要があるアドレスが取得されます2
。
概要
NASM 2.10.09 ELF 出力:
db
魔法のような効果はありません。出力オブジェクト ファイルにバイトを直接出力するだけです。
これらのバイトがたまたまシンボルの前にある場合、シンボルはプログラムの開始時にその値を指します。
テキストセクションにいる場合、バイトが実行されます。
シンボルのサイズを指定しない、db
またはなどを使用する天気:シンボル テーブル エントリのフィールドは影響を受けません。dw
st_size
equ
現在の行のシンボルのst_shndx == SHN_ABS
シンボル テーブル エントリにマジック値を持たせます。
現在のオブジェクト ファイルの場所にバイトを出力する代わりにst_value
、シンボル テーブル エントリのフィールドに出力します。
他のすべてはこれから続きます。
それが実際に何を意味するのかを理解するには、まず ELF 標準とrelocationの基本を理解する必要があります。
SHN_ABS理論
SHN_ABS
リンカーに次のように指示します。
st_value
フィールドは値として直接使用されますこれを「通常の」シンボルと比較してください。この場合、シンボルの値は代わりにメモリアドレスであり、したがって再配置を行う必要があります。
メモリを指していないため、SHN_ABS
シンボルをインライン化することにより、リンカーによって実行可能ファイルからシンボルを効果的に削除できます。
しかし、それらは依然としてオブジェクトファイルの通常のシンボルであり、そこでメモリを占有し、グローバルであれば複数のファイル間で共有できます.
使用例
section .data
x: equ 1
y: db 2
section .text
global _start
_start:
mov al, x
; al == 1
mov al, [y]
; al == 2
シンボルx
にはリテラル値が含ま[]
れているため、 for のように逆参照を行ってはならないことに注意してくださいy
。
x
C プログラムから使用したい場合は、次のようなものが必要です。
extern char x;
printf("%d", &x);
そしてasmに設定します:
global x
生成された出力の経験的観察
前に述べたことを次のように観察できます。
nasm -felf32 -o equ.o equ.asm
ld -melf_i386 -o equ equ.o
今:
readelf -s equ.o
内容:
Num: Value Size Type Bind Vis Ndx Name
4: 00000001 0 NOTYPE LOCAL DEFAULT ABS x
5: 00000000 0 NOTYPE LOCAL DEFAULT 1 y
Ndx
はですので、 であるのにではないことがst_shndx
わかります。x
SHN_ABS
y
も参照しSize
てください。そこに 2 バイトを割り当てる 2 つのディレクティブを追加するだけです。0
y
db
y
db
その後:
objdump -dr equ
与えます:
08048080 <_start>:
8048080: b0 01 mov $0x1,%al
8048082: a0 88 90 04 08 mov 0x8049088,%al
したがって、再配置アドレスの値を取得し0x1
ながら、それが命令にインライン化されていることがわかります。y
0x8049088
Ubuntu 14.04 AMD64 でテスト済み。
ドキュメント
http://www.nasm.us/doc/nasmdoc3.html#section-3.2.4 :
EQU は、シンボルを特定の定数値に定義します。EQU を使用する場合、ソース行にはラベルが含まれている必要があります。EQU のアクションは、指定されたラベル名をその (唯一の) オペランドの値に定義することです。この定義は絶対的なものであり、後で変更することはできません。たとえば、
message db 'hello, world'
msglen equ $-message
msglen を定数 12 に定義します。その後、msglen を再定義することはできません。これもプリプロセッサ定義ではありません: msglen の値は、参照されるたびに評価され、 の値を使用するのではなく、定義の時点で $ の値 ($ の説明についてはセクション 3.5 を参照) を使用して一度評価されます$ 参照ポイントで。
こちらもご覧ください
GAS の類似の質問: ARM アセンブリでの .equ と .word の違いは? .equiv
近いGASに相当するようです。