แอสเซมบลี - คำแนะนำทางคณิตศาสตร์

คำแนะนำ INC

คำสั่ง 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 ใช้สำหรับการเพิ่ม / ลบข้อมูลไบนารีอย่างง่ายในขนาดไบต์คำและคำคู่เช่นสำหรับการเพิ่มหรือลบตัวถูกดำเนินการ 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

The program with hardcoded variables −

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) จะจัดการกับข้อมูลที่ลงนาม คำแนะนำทั้งสองมีผลต่อแฟล็ก Carry และ Overflow

ไวยากรณ์

ไวยากรณ์สำหรับคำสั่ง MUL / IMUL มีดังนี้ -

MUL/IMUL multiplier

ตัวคูณในทั้งสองกรณีจะอยู่ในตัวสะสมขึ้นอยู่กับขนาดของตัวคูณและตัวคูณและผลิตภัณฑ์ที่สร้างขึ้นจะถูกเก็บไว้ในสองรีจิสเตอร์ขึ้นอยู่กับขนาดของตัวถูกดำเนินการ ส่วนต่อไปนี้อธิบายคำแนะนำของ MUL ในกรณีที่แตกต่างกันสามกรณี -

ซีเนียร์ สถานการณ์
1

When two bytes are multiplied −

ตัวคูณอยู่ในทะเบียน AL และตัวคูณเป็นไบต์ในหน่วยความจำหรือในรีจิสเตอร์อื่น ผลิตภัณฑ์อยู่ใน AX ผลิตภัณฑ์ 8 บิตลำดับสูงจะถูกเก็บไว้ใน AH และ 8 บิตลำดับต่ำจะถูกเก็บไว้ใน AL

2

When two one-word values are multiplied −

ตัวคูณควรอยู่ในทะเบียน AX และตัวคูณเป็นคำในหน่วยความจำหรือรีจิสเตอร์อื่น ตัวอย่างเช่นสำหรับคำสั่งเช่น MUL DX คุณต้องจัดเก็บตัวคูณใน DX และตัวคูณใน AX

ผลิตภัณฑ์ผลลัพธ์คือคำสองคำซึ่งจะต้องมีการลงทะเบียนสองรายการ ส่วนลำดับสูง (ซ้ายสุด) จะถูกเก็บไว้ใน DX และส่วนลำดับล่าง (ขวาสุด) จะถูกเก็บไว้ใน AX

3

When two doubleword values are multiplied −

เมื่อคูณค่า doubleword สองค่าตัวคูณควรอยู่ใน EAX และตัวคูณคือค่า doubleword ที่เก็บไว้ในหน่วยความจำหรือในรีจิสเตอร์อื่น ผลิตภัณฑ์ที่สร้างขึ้นจะถูกเก็บไว้ในรีจิสเตอร์ EDX: EAX กล่าวคือลำดับสูง 32 บิตจะถูกเก็บไว้ในรีจิสเตอร์ EDX และลำดับต่ำ 32 บิตจะถูกเก็บไว้ในทะเบียน EAX

ตัวอย่าง

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

การดำเนินการหารสร้างสององค์ประกอบ - ก quotient และก remainder. ในกรณีของการคูณการล้นจะไม่เกิดขึ้นเนื่องจากมีการใช้รีจิสเตอร์ความยาวสองเท่าเพื่อเก็บผลิตภัณฑ์ไว้ อย่างไรก็ตามในกรณีของการแบ่งอาจเกิดการล้น โปรเซสเซอร์จะสร้างอินเทอร์รัปต์หากเกิดโอเวอร์โฟลว์

คำสั่ง DIV (Divide) ใช้สำหรับข้อมูลที่ไม่ได้ลงชื่อและ IDIV (Integer Divide) ใช้สำหรับข้อมูลที่เซ็นชื่อ

ไวยากรณ์

รูปแบบสำหรับคำสั่ง DIV / IDIV -

DIV/IDIV	divisor

เงินปันผลอยู่ในตัวสะสม คำสั่งทั้งสองสามารถทำงานร่วมกับตัวถูกดำเนินการ 8 บิต 16 บิตหรือ 32 บิต การดำเนินการมีผลต่อแฟล็กสถานะทั้งหกสถานะ ส่วนต่อไปนี้อธิบายกรณีการแบ่งสามกรณีที่มีขนาดตัวถูกดำเนินการต่างกัน -

ซีเนียร์ สถานการณ์
1

When the divisor is 1 byte −

เงินปันผลจะถือว่าอยู่ในการลงทะเบียน AX (16 บิต) หลังจากหารแล้วผลหารจะไปที่รีจิสเตอร์ AL และส่วนที่เหลือจะไปที่รีจิสเตอร์ AH

2

When the divisor is 1 word −

การจ่ายเงินปันผลจะถือว่ามีความยาว 32 บิตและในการลงทะเบียน DX: AX 16 บิตลำดับสูงอยู่ใน DX และ 16 บิตลำดับต่ำอยู่ใน AX หลังจากหารแล้วผลหาร 16 บิตจะไปที่รีจิสเตอร์ AX และส่วนที่เหลือ 16 บิตจะไปที่รีจิสเตอร์ DX

3

When the divisor is doubleword −

การจ่ายเงินปันผลจะถือว่ายาว 64 บิตและในการลงทะเบียน EDX: EAX 32 บิตลำดับสูงอยู่ใน EDX และ 32 บิตลำดับต่ำอยู่ใน EAX หลังจากหารแล้วผลหาร 32 บิตจะไปที่รีจิสเตอร์ EAX และส่วนที่เหลือ 32 บิตจะไปที่รีจิสเตอร์ EDX

ตัวอย่าง

ตัวอย่างต่อไปนี้หาร 8 ด้วย 2 dividend 8 ถูกเก็บไว้ในไฟล์ 16-bit AX register และ divisor 2 ถูกเก็บไว้ในไฟล์ 8-bit BL register.

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