มาลองทำ Assembler กัน (พื้นฐาน)
จริง ๆ แล้ว ภาษา assembly มันก็ภาษาเครื่องแหละ แต่มันเขียนสะดวกกว่านิดนึง ... อะไรที่เราควรจะกำหนดเพิ่มไว้ก่อนหละ? ก็เรื่อง label กับ ตัวแปรไง
Local Variables (อีกแล้ว)
สมมติว่า เราจะเขียนว่า
void f()
{
int x;
int y;
x = 0;
y = x + 500;
}
เดิมเราจะเขียนว่า
f:
VAR 2
PBASE
PUSH 1
SUB
PUSH 0
STORE
PBASE
PUSH 2
SUB
PBASE
PUSH 1
SUB
LOAD
PUSH 500
ADD
STORE
...
FVAR
PUSH ค่ามั่ว ๆ อะไรก็ได้
RETURNจะเห็นว่า การอ้างถึงตัว y จะต้องใช้ 3 คำสั่ง คือ
PBASE
PUSH 2
SUBเพื่อลดเรื่องยุ่งพวกนี้ เราก็กำหนดภาษาใหม่ แบบนี้
f:
VAR 2
REF x 1 (บอกให้ x = BP - 1)
REF y 2 (บอกให้ y = BP - 2)
PVAR x
PUSH 0
STORE
PVAR y
PVAR x
LOAD
PUSH 500
ADD
STORE
...
FVAR
PUSH ค่ามั่ว ๆ อะไรก็ได้
RETURNLabels
เราใช้ Label ไปหลายทีแล้วโดยที่ไม่ได้พูดถึง ... จริง ๆ แล้ว การจะกระโดดไปที่ label ต่าง ๆ จำเป็นจะต้องรู้ address ของ label เหล่านั้น ...
ดังนั้น Assembler ของเรา จะต้องมีความสามารถในการ แปลง label เหล่านั้น ให้เป็น address จริง ๆ
สมมติว่ามี code แบบนี้
int f()
{
int x;
int y;
do {
x = ReadFromSomewhere();
y = ReadFromSomewhere();
} while (x != y);
return 0;
}
จะเขียนเป็น Assembly ได้แบบนี้
f:
VAR 2
REF x 1
REF y 2
loop:
PVAR x
PUSH ReadFromSomewhere
CALL
PVAR y
PUSH ReadFromSomewhere
CALL
PVAR x
LOAD
PVAR y
LOAD
SUB
PUSH loop
JNZ
FVAR
PUSH 0
RETURN
ซึ่ง ตอนที่แปลเป็นภาษาเครื่อง เราจะต้องรู้ 3 อย่างคือ- ตำแหน่งเริ่มต้นของ f → สมมติว่าเป็น 1234h
- ตำแหน่งเริ่มต้นของ ReadFromSomewhere → สมมติว่าเป็น 5678h
- ขนาดของ instruction → สมมติว่าเป็น 2
1234h: PUSH
1236h: PUSH
1238h:
PBASE
123Ah:
PUSH 1
123Ch:
SUB
123Eh:
PUSH 5678h
1240h:
CALL
1242h:
PBASE
1244h:
PUSH 2
1246h:
SUB
1248h:
PUSH 5678h
124Ah:
CALL
124Ch:
PBASE
124Eh:
PUSH 1
1250h:
SUB
1252h:
LOAD
1254h:
PBASE
1256h:
PUSH 2
1258h:
SUB
125Ah:
LOAD
125Ch:
SUB
125Eh:
PUSH 1238h
1260h:
JNZ
1262h:
PUSH 0
1264h:
RETURN
คราวหน้า มาดูเรื่อง Literal กันนะ
0 Comments:
Post a Comment
<< Home