組み立て-手順
アセンブリ言語プログラムはサイズが大きくなる傾向があるため、プロシージャまたはサブルーチンはアセンブリ言語では非常に重要です。手順は名前で識別されます。この名前に続いて、明確に定義されたジョブを実行するプロシージャの本体が説明されています。プロシージャの終了は、returnステートメントによって示されます。
構文
以下は、プロシージャを定義するための構文です-
proc_name:
procedure body
...
ret
このプロシージャは、CALL命令を使用して別の関数から呼び出されます。CALL命令には、以下に示すように、呼び出されたプロシージャの名前を引数として指定する必要があります。
CALL proc_name
呼び出されたプロシージャは、RET命令を使用して、制御を呼び出し元のプロシージャに戻します。
例
ECXおよびEDXレジスタに格納されている変数を加算し、EAXレジスタに合計を返すsumという名前の非常に単純なプロシージャを記述してみましょう。
section .text
global _start ;must be declared for using gcc
_start: ;tell linker entry point
mov ecx,'4'
sub ecx, '0'
mov edx, '5'
sub edx, '0'
call sum ;call sum procedure
mov [res], eax
mov ecx, msg
mov edx, len
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov ecx, res
mov edx, 1
mov ebx, 1 ;file descriptor (stdout)
mov eax, 4 ;system call number (sys_write)
int 0x80 ;call kernel
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
sum:
mov eax, ecx
add eax, edx
add eax, '0'
ret
section .data
msg db "The sum is:", 0xA,0xD
len equ $- msg
segment .bss
res resb 1
上記のコードをコンパイルして実行すると、次の結果が得られます。
The sum is:
9
スタックデータ構造
スタックは、メモリ内の配列のようなデータ構造であり、スタックの「トップ」と呼ばれる場所からデータを格納および削除できます。保存する必要のあるデータはスタックに「プッシュ」され、取得されるデータはスタックから「ポップ」されます。スタックはLIFOデータ構造です。つまり、最初に格納されたデータが最後に取得されます。
アセンブリ言語は、スタック操作にPUSHとPOPの2つの命令を提供します。これらの命令には、次のような構文があります。
PUSH operand
POP address/register
スタックセグメントに予約されているメモリスペースは、スタックの実装に使用されます。レジスタSSおよびESP(またはSP)は、スタックの実装に使用されます。スタックに挿入された最後のデータ項目を指すスタックの最上位は、SS:ESPレジスタによって示されます。ここで、SSレジスタはスタックセグメントの先頭を指し、SP(またはESP)はにオフセットを与えます。スタックセグメント。
スタックの実装には次の特徴があります-
のみ words または doublewords バイトではなく、スタックに保存できます。
スタックは逆方向、つまりメモリアドレスの低い方に向かって大きくなります。
スタックの最上位は、スタックに挿入された最後のアイテムを指します。最後に挿入されたワードの下位バイトを指します。
レジスタの値をスタックに格納してから使用することについて説明したように、それは次の方法で行うことができます-
; Save the AX and BX registers in the stack
PUSH AX
PUSH BX
; Use the registers for other purpose
MOV AX, VALUE1
MOV BX, VALUE2
...
MOV VALUE1, AX
MOV VALUE2, BX
; Restore the original values
POP BX
POP AX
例
次のプログラムは、ASCII文字セット全体を表示します。メインプログラムは、ASCII文字セットを表示するdisplayという名前のプロシージャを呼び出します。
section .text
global _start ;must be declared for using gcc
_start: ;tell linker entry point
call display
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
display:
mov ecx, 256
next:
push ecx
mov eax, 4
mov ebx, 1
mov ecx, achar
mov edx, 1
int 80h
pop ecx
mov dx, [achar]
cmp byte [achar], 0dh
inc byte [achar]
loop next
ret
section .data
achar db '0'
上記のコードをコンパイルして実行すると、次の結果が得られます。
0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}
...
...