PROC 文と ENDP 文は、それぞれプロシージャ(手続き、サブルーチン)の開始と終了を宣言します。PROC と ENDP 文は、プログラムを作成するうえで必須ではありませんが、大きなプログラムでは読みやすいコードを作成するうえで効果があります。
構文 label PROC [type][lang][scope][USES regs ... ,][args,...] label ENDP 各 args の構文 name[[num]][:type] 例 SUBR PROC RET SUBR ENDP MYPRC PROC FAR PUBLIC USES AX SI, ARG1[10]:BYTE, ARG2:NEAR PTR MOV AL, ARG1[2] MOV SI, ARG2 MOV BYTE PTR [SI], AL RET MYPRC ENDP
対応する PROC 文と ENDP 文には、同じ label 名を指定する必要があります。label はタイプ type のラベルとして定義されます。
type には、「NEAR」「FAR」「PROC」のいずれかを指定します。デフォルトは「PROC」です。type により、label のタイプと、プロシージャ内の RET 命令が RETN と RETF のどちらになるかが決まります。
lang には、言語モデルを指定します。これにより、プロシージャ名や引数の位置などの呼び出し規約が決まります。
scope には、「PRIVATE」または「PUBLIC」を指定します。デフォルトは PRIVATE です。PUBLIC を指定すると、label を PUBLIC 文で宣言するのと同等の効果があります。PUBLIC を指定した場合は、PUBLIC 文と同様に、続けて「AS as_name」を指定して外部公開名を変更できます。
regs には、16 ビットまたは 32 ビットレジスタ名を空白で区切って指定します。ここに指定したレジスタは、プロシージャの先頭でスタックにプッシュされ、プロシージャ内の RET 命令の直前でポップされます。つまり、そのために必要なコードが自動的に生成されます。RETN 命令、RETF 命令、およびオペランド付きの RET 命令については、ポップ命令は生成されません。
PROC 文では、スタック経由でプロシージャに渡される引数を宣言できます。これは、スタック上の引数に簡単にアクセスするための機能です。引数を宣言する場合は、args を指定します。args には、プロシージャに渡される引数をカンマ(,)で区切って指定します。これにより、スタックに積まれた引数を簡単に参照できるようになります。
args を指定すると、 BP(EBP)レジスタに「スタック フレーム」の値を設定するコードが自動的に生成されます。引数を参照しないプロシージャには args を指定しない方が効率的です。
args で宣言したラベルへの参照は、 BP(EBP)レジスタ相対アドレス参照に置き換えられます。そのため、args を使用するプロシージャ内では、 BP(EBP)レジスタの値を変えずに維持する必要があります。また、args で定義したラベルは、 BP(EBP)レジスタ相対アドレス参照を使用できる命令でのみ使用できます。
例
; ソースコード p proc arg:word mov arg, 7 add arg, ax ret p endp ; 生成コード(アセンブルリスト) p PROC NEAR push bp ;-0000 55 mov bp,sp ;-0001 8B EC add sp,-2h ;-0003 83 C4 FE mov WORD PTR [bp+4h],7h ; 0006 C7 46 04 07 00 (arg) add WORD PTR [bp+4h],ax ; 000B 01 46 04 (arg) mov sp,bp ;-000E 8B E5 pop bp ;-0010 5D retn ; 0011 C3 p ENDP