มาลองทำ 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