Assembly-programming-assembly-arithmetic-instructions

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

アセンブリ-算術命令

INC命令

INC命令は、オペランドを1インクリメントするために使用されます。 これは、レジスタまたはメモリ内にある単一のオペランドで機能します。

構文

INC命令には次の構文があります-

INC destination

オペランド_destination_は、8ビット、16ビット、または32ビットのオペランドにすることができます。

INC EBX      ; Increments 32-bit register
INC DL       ; Increments 8-bit register
INC [count]  ; Increments the count variable

DEC命令

DEC命令は、オペランドを1減らすために使用されます。 これは、レジスタまたはメモリ内にある単一のオペランドで機能します。

構文

DEC命令には次の構文があります-

DEC destination

オペランド_destination_は、8ビット、16ビット、または32ビットのオペランドにすることができます。

segment .data
   count dw  0
   value db  15

segment .text
   inc [count]
   dec [value]

   mov ebx, count
   inc word [ebx]

   mov esi, value
   dec byte [esi]

ADDおよびSUB命令

ADDおよびSUB命令は、バイト、ワード、およびダブルワードサイズのバイナリデータの単純な加算/減算を実行するために、つまり、それぞれ8ビット、16ビット、または32ビットのオペランドを加算または減算するために使用されます。

構文

ADDおよびSUB命令には、次の構文があります-

ADD/SUB destination, source

ADD/SUB命令は次の間に実行できます-

  • 登録して登録する
  • 登録するメモリ
  • メモリに登録する
  • 定数データに登録する
  • 定数データへのメモリ

ただし、他の命令と同様に、ADD/SUB命令を使用したメモリ間操作はできません。 ADDまたはSUB操作は、オーバーフローフラグとキャリーフラグを設定またはクリアします。

次の例では、ユーザーに2桁の数字を要求し、その数字をそれぞれEAXおよびEBXレジスタに保存し、値を追加し、結果をメモリロケーション「res」に保存し、最終的に結果を表示します。

SYS_EXIT  equ 1
SYS_READ  equ 3
SYS_WRITE equ 4
STDIN     equ 0
STDOUT    equ 1

segment .data

   msg1 db "Enter a digit ", 0xA,0xD
   len1 equ $- msg1

   msg2 db "Please enter a second digit", 0xA,0xD
   len2 equ $- msg2

   msg3 db "The sum is: "
   len3 equ $- msg3

segment .bss

   num1 resb 2
   num2 resb 2
   res resb 1

section .text
   global _start    ;must be declared for using gcc

_start:             ;tell linker entry point
   mov eax, SYS_WRITE
   mov ebx, STDOUT
   mov ecx, msg1
   mov edx, len1
   int 0x80

   mov eax, SYS_READ
   mov ebx, STDIN
   mov ecx, num1
   mov edx, 2
   int 0x80

   mov eax, SYS_WRITE
   mov ebx, STDOUT
   mov ecx, msg2
   mov edx, len2
   int 0x80

   mov eax, SYS_READ
   mov ebx, STDIN
   mov ecx, num2
   mov edx, 2
   int 0x80

   mov eax, SYS_WRITE
   mov ebx, STDOUT
   mov ecx, msg3
   mov edx, len3
   int 0x80

   ; moving the first number to eax register and second number to ebx
   ; and subtracting ascii '0' to convert it into a decimal number

   mov eax, [num1]
   sub eax, '0'

   mov ebx, [num2]
   sub ebx, '0'

   ; add eax and ebx
   add eax, ebx
   ; add '0' to to convert the sum from decimal to ASCII
   add eax, '0'

   ; storing the sum in memory location res
   mov [res], eax

   ; print the sum
   mov eax, SYS_WRITE
   mov ebx, STDOUT
   mov ecx, res
   mov edx, 1
   int 0x80

exit:

   mov eax, SYS_EXIT
   xor ebx, ebx
   int 0x80

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Enter a digit:
3
Please enter a second digit:
4
The sum is:
7
  • ハードコードされた変数を持つプログラム- *
section .text
   global _start    ;must be declared for using gcc

_start:             ;tell linker entry point
   mov  eax,'3'
   sub     eax, '0'

   mov  ebx, '4'
   sub     ebx, '0'
   add  eax, ebx
   add  eax, '0'

   mov  [sum], 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,sum
   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

section .data
   msg db "The sum is:", 0xA,0xD
   len equ $ - msg
   segment .bss
   sum resb 1

上記のコードをコンパイルして実行すると、次の結果が生成されます-

The sum is:
7

MUL/IMUL命令

バイナリデータを乗算するための2つの命令があります。 MUL(乗算)命令は符号なしデータを処理し、IMUL(整数乗算)は符号付きデータを処理します。 両方の命令は、キャリーおよびオーバーフローフラグに影響します。

構文

MUL/IMUL命令の構文は次のとおりです-

MUL/IMUL multiplier

両方の場合の被乗数は、被乗数と乗数のサイズに応じてアキュムレータに格納され、生成された積もオペランドのサイズに応じて2つのレジスタに格納されます。 次のセクションでは、3つの異なるケースを持つMUL命令について説明します-

Sr.No. Scenarios
1
  • When two bytes are multiplied −*

被乗数はALレジスタにあり、乗数はメモリまたは別のレジスタのバイトです。 製品はAXにあります。 製品の上位8ビットはAHに格納され、下位8ビットはALに格納されます。

算術1

2

When two one-word values are multiplied −

被乗数はAXレジスタにある必要があり、乗数はメモリ内のワードまたは別のレジスタです。 たとえば、MUL DXのような命令の場合、乗数をDXに、被乗数をAXに保存する必要があります。

結果の積はダブルワードであり、2つのレジスタが必要です。 上位(左端)の部分はDXに格納され、下位(右端)の部分はAXに格納されます。

Arithmetic2

3

When two doubleword values are multiplied −

2つのダブルワード値を乗算する場合、被乗数はEAXである必要があり、乗数はメモリまたは別のレジスタに格納されているダブルワード値です。 生成された製品はEDX:EAXレジスタに保存されます。つまり、上位32ビットがEDXレジスタに保存され、下位32ビットがEAXレジスタに保存されます。

Arithmetic3

MOV AL, 10
MOV DL, 25
MUL DL
...
MOV DL, 0FFH    ; DL= -1
MOV AL, 0BEH    ; AL = -66
IMUL DL

次の例では、3に2を掛けて結果を表示します-

section .text
   global _start    ;must be declared for using gcc

_start:             ;tell linker entry point

   mov  al,'3'
   sub     al, '0'

   mov  bl, '2'
   sub     bl, '0'
   mul  bl
   add  al, '0'

   mov  [res], al
   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

section .data
msg db "The result is:", 0xA,0xD
len equ $- msg
segment .bss
res resb 1

上記のコードをコンパイルして実行すると、次の結果が生成されます-

The result is:
6

DIV/IDIV命令

除算演算は、2つの要素- quotient および remainder を生成します。 乗算の場合、積を保持するために倍長レジスタが使用されるため、オーバーフローは発生しません。 ただし、除算の場合、オーバーフローが発生する可能性があります。 オーバーフローが発生すると、プロセッサは割り込みを生成します。

DIV(除算)命令は符号なしデータに使用され、IDIV(整数除算)は符号付きデータに使用されます。

構文

DIV/IDIV命令の形式-

DIV/IDIV    divisor

配当はアキュムレーターにあります。 どちらの命令も、8ビット、16ビット、または32ビットのオペランドで機能します。 この操作は、6つのステータスフラグすべてに影響します。 次のセクションでは、異なるオペランドサイズの除算の3つのケースについて説明します-

Sr.No. Scenarios
1

When the divisor is 1 byte −

配当はAXレジスタ(16ビット)にあると想定されます。 除算後、商はALレジスタに行き、残りはAHレジスタに行きます。

Arithmetic4

2

When the divisor is 1 word −

配当は32ビット長で、DX:AXレジスタ内にあると想定されます。 上位16ビットはDXにあり、下位16ビットはAXにあります。 除算後、16ビットの商はAXレジスタに送られ、16ビットの余りはDXレジスタに送られます。

算術5

3

When the divisor is doubleword −

被除数は64ビット長で、EDX:EAXレジスタにあると想定されています。 上位32ビットはEDXにあり、下位32ビットはEAXにあります。 除算後、32ビットの商はEAXレジスタに送られ、32ビットの余りはEDXレジスタに送られます。

算術6

次の例では、8を2で割ります。 被除数8 *は 16ビットAXレジスタ*に格納され、除数2 *は 8ビットBLレジスタ*に格納されます。

section .text
   global _start    ;must be declared for using gcc

_start:             ;tell linker entry point
   mov  ax,'8'
   sub     ax, '0'

   mov  bl, '2'
   sub     bl, '0'
   div  bl
   add  ax, '0'

   mov  [res], ax
   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

section .data
msg db "The result is:", 0xA,0xD
len equ $- msg
segment .bss
res resb 1

上記のコードをコンパイルして実行すると、次の結果が生成されます-

The result is:
4