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