Учебники

Сборка — Арифметические инструкции

Инструкция INC используется для увеличения операнда на единицу. Он работает с одним операндом, который может находиться либо в регистре, либо в памяти.

Синтаксис

Инструкция INC имеет следующий синтаксис —

INC destination

Назначением операнда может быть 8-битный, 16-битный или 32-битный операнд.

пример

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

Инструкция DEC

Инструкция DEC используется для уменьшения операнда на единицу. Он работает с одним операндом, который может находиться либо в регистре, либо в памяти.

Синтаксис

Инструкция DEC имеет следующий синтаксис —

DEC 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 устанавливает или очищает переполнение и переносит флаги.

пример

В следующем примере пользователь запросит две цифры, сохранит их в регистре 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

Программа с жестко закодированными переменными —

Live Demo

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

Есть две инструкции для умножения двоичных данных. Инструкция MUL (Multiply) обрабатывает неподписанные данные, а IMUL (Integer Multiply) обрабатывает подписанные данные. Обе инструкции влияют на флаг переноса и переполнения.

Синтаксис

Синтаксис для инструкций MUL / IMUL следующий:

MUL/IMUL multiplier

Мультипликатор в обоих случаях будет в аккумуляторе, в зависимости от размера мультипликатора и умножителя, и сгенерированный продукт также сохраняется в двух регистрах в зависимости от размера операндов. Следующий раздел объясняет инструкции MUL в трех разных случаях:

Sr.No. Сценарии
1

Когда два байта умножены —

Умножитель находится в регистре AL, а множитель — это байт в памяти или в другом регистре. Продукт находится в AX. Старшие 8 битов продукта хранятся в AH, а младшие 8 битов хранятся в AL.

Arithmetic1

2

Когда умножаются два значения в одно слово

Умножитель должен быть в регистре AX, а множитель — это слово в памяти или другой регистр. Например, для такой инструкции, как MUL DX, вы должны сохранить множитель в DX и умножить в AX.

В результате получается двойное слово, для которого понадобятся два регистра. Часть высшего порядка (крайняя слева) сохраняется в DX, а часть нижнего порядка (крайняя справа) сохраняется в AX.

Arithmetic2

3

Когда два значения двойного слова умножаются —

Когда умножаются два значения двойного слова, множитель должен быть в EAX, а множитель — это значение двойного слова, хранящееся в памяти или в другом регистре. Сгенерированный продукт сохраняется в регистрах EDX: EAX, т. Е. 32-разрядные старшие разряды сохраняются в регистре EDX, а 32-разрядные старшие разряды хранятся в регистре EAX.

Arithmetic3

Когда два байта умножены —

Умножитель находится в регистре AL, а множитель — это байт в памяти или в другом регистре. Продукт находится в AX. Старшие 8 битов продукта хранятся в AH, а младшие 8 битов хранятся в AL.

Arithmetic1

Когда умножаются два значения в одно слово

Умножитель должен быть в регистре AX, а множитель — это слово в памяти или другой регистр. Например, для такой инструкции, как MUL DX, вы должны сохранить множитель в DX и умножить в AX.

В результате получается двойное слово, для которого понадобятся два регистра. Часть высшего порядка (крайняя слева) сохраняется в DX, а часть нижнего порядка (крайняя справа) сохраняется в AX.

Arithmetic2

Когда два значения двойного слова умножаются —

Когда умножаются два значения двойного слова, множитель должен быть в 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 и отображается результат:

Live Demo

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

Операция деления генерирует два элемента — частное и остаток . В случае умножения переполнение не происходит, потому что регистры двойной длины используются для хранения продукта. Однако в случае деления может произойти переполнение. Процессор генерирует прерывание, если происходит переполнение.

Инструкция DIV (Divide) используется для данных без знака, а IDIV (Integer Divide) используется для данных со знаком.

Синтаксис

Формат для инструкции DIV / IDIV —

DIV/IDIV	divisor

Дивиденд находится в аккумуляторе. Обе инструкции могут работать с 8-битными, 16-битными или 32-битными операндами. Операция влияет на все шесть флагов состояния. Следующий раздел объясняет три случая деления с различным размером операнда —

Sr.No. Сценарии
1

Когда делитель равен 1 байту —

Предполагается, что дивиденд находится в регистре AX (16 бит). После деления частное переходит в регистр AL, а остальное — в регистр AH.

Arithmetic4

2

Когда делителем является 1 слово —

Предполагается, что дивиденды имеют длину 32 бита и в регистрах DX: AX. Старшие 16 битов находятся в DX, а младшие 16 битов — в AX. После деления 16-битное отношение попадает в регистр AX, а 16-битное значение попадает в регистр DX.

Arithmetic5

3

Когда делитель двойное слово —

Предполагается, что размер дивиденда составляет 64 бита и в регистрах EDX: EAX. Старшие 32 бита находятся в EDX, а младшие 32 бита находятся в EAX. После деления 32-битное отношение попадает в регистр EAX, а 32-битное значение попадает в регистр EDX.

Arithmetic6

Когда делитель равен 1 байту —

Предполагается, что дивиденд находится в регистре AX (16 бит). После деления частное переходит в регистр AL, а остальное — в регистр AH.

Arithmetic4

Когда делителем является 1 слово —

Предполагается, что дивиденды имеют длину 32 бита и в регистрах DX: AX. Старшие 16 битов находятся в DX, а младшие 16 битов — в AX. После деления 16-битное отношение попадает в регистр AX, а 16-битное значение попадает в регистр DX.

Arithmetic5

Когда делитель двойное слово —

Предполагается, что размер дивиденда составляет 64 бита и в регистрах EDX: EAX. Старшие 32 бита находятся в EDX, а младшие 32 бита находятся в EAX. После деления 32-битное отношение попадает в регистр EAX, а 32-битное значение попадает в регистр EDX.

Arithmetic6

пример

В следующем примере делится 8 на 2. Дивиденд 8 сохраняется в 16-битном регистре AX, а делитель 2 сохраняется в 8-битном регистре BL .

Live Demo

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

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —