Assembly-programming-assembly-procedures

提供:Dev Guides
移動先:案内検索

組み立て-手順

アセンブリ言語プログラムはサイズが大きくなる傾向があるため、プロシージャまたはサブルーチンはアセンブリ言語で非常に重要です。 プロシージャは名前で識別されます。 この名前に続いて、明確に定義されたジョブを実行するプロシージャの本体が説明されています。 プロシージャの終了は、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{|}
...
...