การประกอบ - ขั้นตอน
โพรซีเดอร์หรือรูทีนย่อยมีความสำคัญมากในภาษาแอสเซมบลีเนื่องจากโปรแกรมภาษาแอสเซมบลีมักจะมีขนาดใหญ่ ขั้นตอนถูกระบุโดยชื่อ ตามชื่อนี้จะมีการอธิบายเนื้อหาของโพรซีเดอร์ซึ่งทำงานได้ดี สิ้นสุดขั้นตอนจะระบุโดยคำสั่งส่งคืน
ไวยากรณ์
ต่อไปนี้เป็นไวยากรณ์เพื่อกำหนดขั้นตอน -
proc_name:
procedure body
...
ret
โพรซีเดอร์ถูกเรียกใช้จากฟังก์ชันอื่นโดยใช้คำสั่ง CALL คำสั่ง CALL ควรมีชื่อของขั้นตอนที่เรียกว่าเป็นอาร์กิวเมนต์ดังที่แสดงด้านล่าง -
CALL proc_name
ขั้นตอนที่เรียกว่าจะส่งคืนการควบคุมไปยังขั้นตอนการเรียกโดยใช้คำสั่ง RET
ตัวอย่าง
ให้เราเขียนขั้นตอนง่ายๆที่ชื่อsumที่เพิ่มตัวแปรที่เก็บไว้ในทะเบียน ECX และ EDX และส่งกลับผลรวมในทะเบียน EAX -
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
โครงสร้างข้อมูลกองซ้อน
สแต็กคือโครงสร้างข้อมูลที่เหมือนอาร์เรย์ในหน่วยความจำซึ่งข้อมูลสามารถจัดเก็บและลบออกจากตำแหน่งที่เรียกว่า 'ด้านบน' ของสแต็ก ข้อมูลที่ต้องจัดเก็บจะถูก 'ผลัก' เข้าไปในสแต็กและข้อมูลที่จะดึงออกมาจะถูก 'ดึง' ออกจากสแต็ก Stack เป็นโครงสร้างข้อมูลแบบ LIFO กล่าวคือข้อมูลที่เก็บไว้ก่อนจะถูกดึงมาล่าสุด
ภาษาแอสเซมบลีมีคำสั่งสองคำสั่งสำหรับการดำเนินการสแต็ก: 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 ทั้งหมด โปรแกรมหลักเรียกขั้นตอนที่ชื่อว่าdisplayซึ่งแสดงชุดอักขระ ASCII
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{|}
...
...