150 likes | 288 Vues
CS344-321 Assembly Language Programming. Period 32. PARAMETER PASSING ในภาษาระดับสูง เมื่อมีการเรียกใช้โปรแกรมย่อย พารามิเตอร์อาจจะส่งผ่านทาง เรจิสเตอร์ หรือกองซ้อน หรือผสมกัน
E N D
CS344-321 Assembly Language Programming Period 32
PARAMETER PASSING ในภาษาระดับสูง เมื่อมีการเรียกใช้โปรแกรมย่อย พารามิเตอร์อาจจะส่งผ่านทาง เรจิสเตอร์ หรือกองซ้อน หรือผสมกัน การผ่านทางเรจิสเตอร์จะเร็วกว่า แต่มีข้อจำกัด เนื่องจากจำนวน เรจิสเตอร์มีน้อย ถ้ามีพารามิเตอร์จำนวนมากไม่สามารถผ่านทางเรจิสเตอร์ได้หมด ต่อไปจะกล่าวถึงเฉพาะการผ่านพารามิเตอร์ทางกองซ้อน เนื่องจากการผ่านพารามิเตอร์ทางเรจิสเตอร์ตรงไปตรงมา ไม่ต้องกล่าวถึงอีก (ดูตัวอย่างการเรียกใช้บริการของ BIOS หรือ DOS หรือ atoi หรือ itoa) ตามข้อตกลงของภาษาระดับสูง เมื่อมีการเรียกใช้โปรแกรมย่อย จะเกิดกรอบกองซ้อน (activation record หรือ stack frame) ดังนี้
parameter1 stack parameter2 … จัดการโดยผู้เรียก bp + 6 parametern -1 bp + 4 parameter n bp + 2return address bp dynamic link bp - 2 local variable 1 bp - 4 local variable 2 จัดการโดยผู้ถูกเรียก … local variable n กรณี near call
parameter1 stack parameter2 … จัดการโดยผู้เรียก bp + 8 parametern -1 bp + 6 parameter n bp + 2return address bp dynamic link bp - 2 local variable 1 bp - 4 local variable 2 จัดการโดยผู้ถูกเรียก … local variable n กรณี far call
ผู้เรียกจะดำเนินการต่อไปนี้ผู้เรียกจะดำเนินการต่อไปนี้ - ถ้ามีพารามิเตอร์ กดค่าหรือเลขที่ของพารามิเตอร์ (ขึ้นอยู่กับว่าเป็นการส่งพารามิเตอร์แบบไหน) ลงบนกองซ้อนในช่วงกระทำการตามลำดับจากตัวแรกถึงตัวสุดท้าย ถ้าเป็นภาษาปาสคาล ตัวสุดท้ายจะอยู่บนสุด แต่ถ้าเป็นภาษาซี จะทำกลับกัน - เรียกใช้ชุดคำสั่งย่อยหรือฟังก์ชันที่ต้องการ ภาษาแอสเซมบลี 8086/8088 มีคำสั่ง call ซึ่งทำหน้าที่นี้โดยตรง คำสั่ง call จะกดเลขที่กลับ (return address: เลขที่ของคำสั่งถัดจากคำสั่ง call) ลงบนกองซ้อนในช่วงกระทำการ แล้วกระโดดไปทำงานที่ชุดคำสั่งย่อยหรือฟังก์ชันที่ต้องการ (สถาปัตยกรรมบางแบบไม่มีคำสั่ง call โดยตรง ในกรณีนี้ต้องกดเลขที่กลับมาทำงานต่อ ลงบนกองซ้อนในช่วงกระทำการ แล้วใช้คำสั่งกระโดด เพื่อไปทำงานที่ชุดคำสั่งย่อยหรือฟังก์ชันที่ต้องการเอง)
ตัวอย่างภาษา Pascal • procedure subr(para1:integer, var para2:integer, …, paran:integer) • เรียกใช้ด้วย • subr(para1, para2, …, paran); • ภาษาเอสเซมบลี • mov ax,para1 ; call by value • push ax • lea ax,para2 ; call by reference • push ax • … • mov ax,paran ; call by value • push ax • call subr
ตัวอย่างภาษา C ซึ่งมีวิธีการผ่านค่าโดย value เท่านั้น subr(int para1, int para2, …, int paran) เรียกใช้ด้วย subr(para1, para2, …, paran); ภาษาเอสเซมบลี mov ax,paran push ax ... mov ax,para2 push ax mov ax,para1 push ax call subr
ผู้ถูกเรียก จะมีการดำเนินการ ดังต่อไปนี้ • - กดค่าโยงพลวัต (dynamic link) ลงบนกองซ้อนในช่วงกระทำการ • - จองเนื้อที่ให้กับตัวแปรท้องถิ่นบนกองซ้อนในช่วงกระทำการ • เขียนเป็นคำสั่งภาษาแอสเซมบลี 8086/8088 ได้ ดังนี้ • subr proc near • push bp ; dynamic link • mov bp,sp • sub sp,_total_local_sizes • เมื่อ total_parm_sizes เป็นเลขจำนวนเต็ม มีค่าเท่ากับขนาดของพารามิเตอร์รวมกันทั้งหมด
เมื่อผู้ถูกเรียกทำงานเสร็จ จะต้องลบกรอบกองซ้อนทิ้ง วิธีการลบทำได้ง่าย ๆ โดยการใช้คำสั่ง ต่อไปนี้ mov sp,bp pop bp ret total_parm_sizes subr endp เมื่อ total_parm_sizes เป็นเลขจำนวนเต็ม มีค่าเท่ากับขนาดของพารามิเตอร์รวมกันทั้งหมด
ตัวอย่าง จากโปรแกรมภาษาปาสกาล ข่อไปนี้ program final(input,output); var i,j:integer; procedure swap(var x,y:integer); var t : integer; begin t:=x; x:=y; y:=t; end; begin swap(i,j); end. จงเขียนโปรแกรมภาษาแอสเซมบลี 8086/8088 ให้ทำงานเหมือนโปรแกรมภาษา Pascal ข้างต้น โดยให้มีการผ่านพารามิเตอร์ทางกองซ้อน ตามข้อตกลงของภาษา Pascal
dosseg • .model small • .stack 128 • .data • ; define global variables here • i dw ? • j dw ?
.code • swap proc near • x equ [bp+6] ; parameter x • y equ [bp+4] ; parameter y • t equ [bp-2] ; local variable t • push bp ; save old bp as dynamic link • mov bp,sp ; set bp point to stack frame • sub sp,2 ; allocate space for t • push bx ; save content of bx • mov bx,x ; t := x be careful x keeps address of i not value of i • mov ax,[bx] ; keep value of x in ax • mov t,ax ; then copy to t • mov bx,y ; x:=y be careful x and y keep address of i and j • mov ax,[bx] ; keep value of y in ax • mov bx,x • mov [bx],ax ; then copy to x • mov ax,t ; y:=t , keep value of t in ax • mov bx,y ; next instruction will copy to y • mov [bx],ax ; after this i and j should be exchanged value
pop bx ; restore content of bx • mov sp,bp • pop bp • ret 4 • swap endp • main proc near • mov ax,@data • mov ds,ax • lea ax,i ; pass parameters (Pascal Convention) • push ax • lea ax,j • push ax • call swap ; call swap • mov ax,4c00h • int 21h • main endp • end main
กรณี nested call หรือ recursive call เช่น main call A แล้ว A call B main{ … ; call A; … } proc A { …; call B; … } proc B { … } จะเกิด stack frame บน stack ดังนี้ หมายเหตุ แสดงเฉพาะ dynamic link และ stack frame pointer
bp ของ main เป็นอะไร ก็ได้ bp stack frame ของ A bp stack frame ของ B