Assembly-programming-assembly-procedures
組み立て-手順
アセンブリ言語プログラムはサイズが大きくなる傾向があるため、プロシージャまたはサブルーチンはアセンブリ言語で非常に重要です。 プロシージャは名前で識別されます。 この名前に続いて、明確に定義されたジョブを実行するプロシージャの本体が説明されています。 プロシージャの終了は、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データ構造です。つまり、最初に保存されたデータが最後に取得されます。
アセンブリ言語は、スタック操作のための2つの命令PUSHとPOPを提供します。 これらの指示には次のような構文があります-
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{|}
...
...