Transcript HW200_12

С.Байгалтөгс. ШУТИС-КТМС
2009/Хавар
[www.cdeq.mn/hw200]
[www.cdeq.mn/hw200]
[www.cdeq.mn/hw200]
Энэ сэдвээр стек болон стекийн заагч регистр
$sp-н тухай үзнэ.
Бүлгийн сэдвүүд:
 Стек
 Стекийн заагч регистр $sp
 Стекийн Push ба Pop үйлдлүүд.
 MIPS стек.
 Стекийн хөрвүүлэлтийн хэрэглээ.
 Жишээ тэмдэгт мөрийн урвуу хэлбэр.
 Анхааруулга: Энэ бүлэг дэх жишээ програмууд нь ,
SPIM симуляторийн псевдокомандууд нь ON
,
delayed branches нь OFF,
мөн delayed loading нь OFF юм.

[www.cdeq.mn/hw200]


Стек нь санах ойд өгөгдөл зохион байгуулах
аргачлал юм. Стек дэх өгөгдлүүдийн харагдац
нь өрсөн тавагнууд шиг харагддаг байна.
Өгөгдлүүдийг стек бүтцэд нэмэх эсвэл хасах нь
өрсөн таваг нэмэх эсвэл эсвэл хасах аналог
замаар явагддаг.
Энгийн үед стекийн бүх үйлдэл оройн хэсэгт
(top) хийгдэнэ. Хэрэв таваг нэмэх хэрэгтэй бол
тавгаа стекийн оройд байрлуулна.
[www.cdeq.mn/hw200]





Стек маягын үйл явцыг заримдаа "LIFO" буюу Last In
First Out гэж нэрлэдэг.
Манай хичээлийн стек дэх өгөгдлийн элементүүд 32-бит
үг (word) урттай. Ерөнхийдөө стекийг өгөгдлийн бүх
төрөлд ашиглах боломжтой. Харин энэ сэдэвт стек нь
зөвхөн 32-бит MIPS үг (word) агуулах юм.
Зурган дээр MIPS-ийн үг агуулсан стекийг үзүүлэв.
Стекийн заагч регистр (Stack point register) болох $sp
нь стекийн оройн хэсгийг заана. Стек заагч нь
регистр $29 юм. Мнемоник регистр нэр $sp нь
өргөтгөсөн ассемблерт ашиглагдана.
Хэвийн тохиолдолд стек санах ойг зурахдаа урвуу
хэлбэртэй зурдаг. Зурган дээр стекийн оройн хэсэг нь 81
болох юм. Стекийн доод хэсэг нь -92 гэсэн бүхэл тоон
утгыг агуулжээ.
Үйлдлийн систем эхлэхээс өмнө програм стект
тохирсон санах ойн хязгаар бий эсэхийг баталгаажуулж
тохирох хаягыг $sp-д өгнө.
[www.cdeq.mn/hw200]
[www.cdeq.mn/hw200]


Програм хангамжийн хувьд $sp нь үргэлж стекийн
оройн хэсгийг заана. Түүнчлэн стек нь доош буурах
замаар өсдөг (Санах ойн хаягын зарчимаар). Иймд
манай 4-байтын (full word) өгөгдөлтэй стекийн хувьд
өгөгдөл нэмэхдээ $sp-ээс 4-ийг хасаж тухайн хаягт
өгөгдлийг хадгална. Энэ үйлдлийг push гэж нэрлэнэ.
Өгөгдлийг стек рүү push хийхэд эхэлж стек заагчийн
утгаас 4-ийг хасаж дараа нь стек заагчийн хаягт
түүнийг хадгалдаг. Код дээр хэрхэн харагдахыг
үзүүлэв. Стект оруулах утга нь регистр $t0-д
хадгалагдаж байна:
# Өгөгдлийг PUSH the item in $t0:
subu $sp,$sp,4
# шинэ өгөгдлийн байрлалыг
заана,
sw $t0,($sp)
# $t0-н агуулгыг тухайн шинэ
байрлал болгон хадгална
[www.cdeq.mn/hw200]
[www.cdeq.mn/hw200]



Стекээс өгөгдлийг гаргах үйлдлийг pop гэж нэрлэдэг. Програм
хангамжийн хувьд стекээс өгөгдлийг “гаргах” үйлдэл гэдэг нь
өгөгдлийг өөр байрлал руу хуулах ба стек заагч нь дахин
тохируулагддаг гэж ойлгогдож болох юм.
Зурган дээр pop үйлдлийг үзүүлжээ. Эхлээд өгөгдөл стекийн
оройн хэсгээс шинэ байрлал руу хуулагдаж дараа нь стекийн
заагч нь 4-өөр нэмэгдэнэ.
Стекийн оройн элементийг pop хийхэд стек заагчийн зааж
байгаа элементийг хуулсаны дараа стек заагчийн утга дээр 4ийг нэмэх юм. Код дээр хэрхэн бичигдсэнийг үзүүлэв. Утгыг $t0
руу гаргая гэж санавал:
# $t0 руу элементийг гаргах:
lw $t0,($sp)
# Элементийг $t0 руу хуулна.
addu $sp,$sp,4 # Хуучин оройн хэсгийн доор байрлах
элементийг заана.
[www.cdeq.mn/hw200]
[www.cdeq.mn/hw200]



Регистрүүд ашиглагдаж байх үед стекийг ихэвчлэн
өгөгдлийн утгыг түр зуур хадгалах зориулалтаар
ашигладаг. Үүний жишээ нь стек ашиглан
хөрвүүлэгч хэрхэн арифметик илэрхийллийг машин
код руу хөрвүүлэхийг үзье.
Арифметик илэрхийлэл нь ab - 12a + 18b – 7 ба
зөвхөн регистр $t0 ба $t1-г ашиглах боломжтой.
SPIM нь програмыг ажиллуулж эхлэхээс өмнө стек
заагч $sp-ийн утгыг зөв тодорхойлно. Бүхий л
компьютер дээр стек заагчийн утгыг хэрэглэгчийн
програм эхлэхээс өмнө үйлдлийн системээр
тодорхойлогддог.
Жишээ програм:
[www.cdeq.mn/hw200]









# ab - 12a + 18b - 7
main: lw $t0,a
# get a
lw $t1,bb
# get b
mul $t0,$t0,$t1
# a*b
subu $sp,$sp,_____ # push a*b onto stack
sw $t0,______ . . . . .
.data
a: 2
bb: 3
[www.cdeq.mn/hw200]

Илэрхийллийн элементүүдийг стек рүү
орууллаа (push). Дараа нь нийлбэрийн утга -7
гэж тавигдах ба элементүүдийг стекээс гаргаж
(pop) нийлбэр дээр нэмнэ.
[www.cdeq.mn/hw200]





















# ab - 12a + 18b - 7
.globl main
lw $t0,a
# get a
lw $t1,bb
# get b
mul $t0,$t0,$t1
# a*b
subu $sp,$sp,4
# push a*b onto stack
sw $t0,($sp)
lw $t0,a
# get a
li $t1,-12
#
mul $t0,$t0,$t1
# -12a
subu $sp,$sp,4
# push -12a onto stack
sw $t0,($sp)
lw $t0,bb
# get b
li $t1,18
#
mul $t0,$t0,$t1
# 18b
subu $sp,$sp,4
# push 18b onto stack
sw $t0,($sp)
li $t1,-7
# init sum to -7
lw $t0,_____
# pop 18b
addu $sp,$sp,______
addu $t1,$t1,$t0
# 18b -7 . . . .
[www.cdeq.mn/hw200]

Хэрэв их хэмжээний регистрүүд боломжтой
байсан бол илэрхийллийг стект биш
регистрүүдэд хадгалаад явах боломжтой юм.
Гэхдээ том хэмжээтэй програмд олон
регистрүүд ашигласан ч яг энэ зарчмаар
үйлдлүүд хийгдэнэ. Програмын бүтэн
хувилбарыг үзүүлэв:
[www.cdeq.mn/hw200]














# ab - 12a + 18b - 7
# Settings: Load delays OFF; Branch delays OFF,
# Trap file ON; Pseudoinstructions ON
.globl main
main: lw $t0,a
# get a
lw $t1,bb
# get b
mul $t0,$t0,$t1 # a*b
subu $sp,$sp,4
# push a*b onto stack
sw $t0,($sp)
lw $t0,a
# get a
li $t1,-12
#
mul $t0,$t0,$t1 # -12a
subu $sp,$sp,4 # push -12a onto stack
sw $t0,($sp)
[www.cdeq.mn/hw200]





















lw $t0,bb
# get b
li $t1,18
#
mul $t0,$t0,$t1
# 18b
subu $sp,$sp,4
# push 18b onto stack
sw $t0,($sp)
li $t1,-7
# init sum to -7
lw $t0,($sp)
# pop 18b
addu $sp,$sp,4
addu $t1,$t1,$t0 # 18b -7
lw $t0,($sp)
# pop -12a
addu $sp,$sp,4
addu $t1,$t1,$t0
# -12a + 18b -7
lw $t0,($sp)
# pop ab
addu $sp,$sp,4
addu $t1,$t1,$t0
# ab - 12a + 18b -7
done: li $v0,1
# print sum
move $a0,$t1
# syscall
li $v0,10
# exit syscall
.data
a:
.word 0
bb: .word 10
[www.cdeq.mn/hw200]


Хамгийн сайн компьютерийн системд ч
хязгаарлагдмал санах ойн орон зай байдаг.
Иймээс програм анх ачаалагдахад үйлдлийн
систем нь их хэмжээний стек зай өгдөг.
Зурган дээр үйлдлийн систем хэрхэн програмыг
эхлэхэд санах ойг хэрхэн хуваарилж байгаа
үзүүлжээ. 4Гбайтын боломжит санах ой байна.
Санах ойн хэсэг нь 0x10000000-ээс
0x7FFFFFFF хүртэлх зайнд өгөгдлийн сегмент
болон стек сегментэд зай гаргаж өгчээ. Энэ нь
1.8 Гигабайт зай.
[www.cdeq.mn/hw200]
[www.cdeq.mn/hw200]


Програм эхлэхдээ санах ойн заагчийн ($sp)
утгыг 0x7FFFEFFC (хэрэглэгчийн санах ойн
оройн хэсгийн доор байрлах үг (full word)-ийн
хаяг) болгоно. Програм ажиллахад стек нь
боломжит зай хүртэл доош чиглэж өснө. Харин
өгөгдлийн сегмент нь дээш чиглэж өснө.
Мэдээж динамик програмд сегментийг өсөж бас
агшдаг. Хэрэв сегментүүдийн нэгдсэн зай нь
боломжит зайнаас хэтэрвэл тэдгээрийн зааг нь
хязгаарын дунд хэсгийн хаа нэгтэй тааралдана.
Ингэвэл санах ой үлдээгүй гэсэн үг юм.
Санах ой зохицуулах арга нь 0x10000000 ээс
0x7FFFFFFF хоорондох зайн хагасыг стект,
хагасыг нь өгөгдөлд хуваарилах явдал юм.
[www.cdeq.mn/hw200]


Заншил ёсоор бол машин командын сегментийг
“text” нэрлэдэг. Сегмент ажиллаж эхлэх үед
“process” гэж нэрлэгдэнэ.
Энд стекийн хэрэглээний сонгодог жишээг үзүүлэв.
Хэрэглэгч тэмдэгт мөр оруулах ба програм үүнийг
нь урвуу болгон гаралт руу бичнэ. Програмын
хэрхэн ажиллаж байгааг ойлгохын тулд дараах
диаграмыг үзүүлжээ. Тэмдэгт мөр "Hello“-г тэмдэгт
тэмдэгтээр нь стек рүү push хийв. Дараа нь
тэмдэгтүүд стекээс буцаж эх тэмдэгт мөр рүүгээ
pop хийгдэнэ. Стек руу оруулсан сүүлийн тэмдэгт
эхэнд стекээс гарна. Энэ үйлдэл нь тэмдэгтүүдийн
байрыг сольж урвуу болгох юм.
[www.cdeq.mn/hw200]

Стек дэх тэмдэгт бүр үгний (full word) доод
эрэмбийн байтад хадгалагдах 2 байт хэмжээтэй
юм.
[www.cdeq.mn/hw200]

Програмын дүгнэлт. Тайлбарууд нь програмын гол
хэсгийг илэрхийлнэ.
.text
.globl main
main:
# input the string
# push each character onto the stack
# pop chars from stack back into the
buffer
# print the reversed string
.data
str: .space 128
# character buffer
[www.cdeq.mn/hw200]


Програмын эхний хэсэг нь терминалаас нэг
мөр уншина.
Дараа нь, стекийн утгыг тохируулна. Null утгыг
стек руу оруулна(push). Үүний дараа, энэ null
хүртэлх утгуудыг гаргана (pop).
[www.cdeq.mn/hw200]
















# Reverse and output a user-supplied string
# Settings: Load delays OFF; Branch delays OFF,
# Trap file ON; Pseudoinstructions ON
# $t0 --- character pushed or popped
# $t1 --- index into string buffer str
.text
.globl main
main:
# input the string
li $v0,8
# service code
la $a0,str
# address of buffer
li $a1,128
# buffer length syscall
# initialize the stack:
li $t0,_____
# push a null
____ $sp,$sp,4 # onto the stack
sw $t0,(___)
# to signal its bottom
li $t1,0
# index of first char in str buffer
[www.cdeq.mn/hw200]





# push each character onto the stack
# pop chars from stack back into the buffer
# print the reversed string
.data
str: .space 128
# character buffer
[www.cdeq.mn/hw200]


Дараагийн алхам нь, тэмдэгтийн буфер дэх
тэмдэгтүүдийг стек рүү нэг нэгээр нь оруулах
юм. Эхний командыг тэмдэгтийг буферээс $t0-н
байт руу ачаалахад ашиглана.
Дараа нь, ачаалсан тэмдэгтийг шалгана.Хэрэв
энэ нь null (тэмдэгт) бол давталтаас гадуур
салаалалтыг удирдана. Үгүй бол тэмдэгтийг
стек руу оруулна (push). Гэх мэтээр энэ
процесс давтагдана.
[www.cdeq.mn/hw200]















# Reverse and output a user-supplied string
# Settings: Load delays OFF; Branch delays OFF,
# Trap file ON; Pseudoinstructions ON
# $t0 --- character pushed or popped
# $t1 --- index into string buffer str
.text
.globl main
main:
# input the string
li $v0,8
# service code
la $a0,str
# address of buffer
li $a1,128
# buffer length syscall
li $t0,0
# push a null
subu $sp,$sp,4 # onto the stack
sw $t0,($sp)
# to signal its bottom
li $t1,0
# index of first char in str buffer
[www.cdeq.mn/hw200]











# push each character onto the stack
pushl:
lbu $t0,str($t1)
# get current char into # a
full word
____ $t0,stend
# null byte: end of string
subu $sp,$sp,4
# push the full word
___ $t0,($sp)
# holding the char
addu $t1,1
# inc the index
j _____
# loop
stend: . . . . .
# pop chars from stack back
into the buffer
# print the reversed
string
.data
str: .space 128
# character buffer
[www.cdeq.mn/hw200]


Тэмдэгт мөр дэх Null байт тааралдвал эхний
давталт төгсөж дараагийн давталт эхлэнэ. Энэ
дараагийн давталт нь стекийн доод хэсэгт
байрлах null тэмдэгт дайралдах хүртэл
тэмдэгтүүдийг стекээс гаргах юм. Стекээс гарах
тэмдэгт бүр буферт хадгалагдах хуучин
тэмдэгтүүдийг дарж хуулагдана.
Тэмдэгт мөрийн төгсгөлд байрлах null тэмдэгт
дарж хуулагдахгүй.
[www.cdeq.mn/hw200]



















. . . . . # push each
pushl:
lbu $t0,str($t1)
beqz $t0,stend
subu $sp,$sp,4
sw $t0,($sp)
addu $t1,1
j pushl
stend:
li $t1,0
popl:
____ $t0,($sp)
____ $sp,$sp,4
beqz $t0,done
____ $t0,str($t1)
addu $t1,1
j popl
.data
str: .space 128
character onto the stack
# get current char into # a full word
# null byte: end of string
# push the full word
# holding the char
# inc the index
# loop # pop chars from stack back into the buffer
# index of first byte of str buffer
# pop a char off the stack
# null means empty stack
# store at string[$t1]
# inc the index
# loop # print the reversed string . . . . .
# character buffer
[www.cdeq.mn/hw200]

Програмын сүүлчийн шатанд тэмдэгтэн үр
дүнг дэлгэцэнд хэвлэнэ.
[www.cdeq.mn/hw200]















. . . . . # pop chars from stack back into the buffer
stend:
li $t1,0
# index of first byte of str buffer
popl:
lw $t0,($sp)
# pop a char off the stack
addu $sp,$sp,4
beqz $t0,done
# null means empty stack
sb $t0,str($t1)
# store at string[$t1]
addu $t1,1
# inc the index
j popl
# loop # print the reversed string
done: li $v0,4
# service code
la $a1,str
# address of string syscall
li $v0,10
# exit syscall
.data
str: .space 128
# character buffer
[www.cdeq.mn/hw200]
Бүлэгт үзсэн сэдвүүд
 Стекийн талаарх ойлголт.
 LIFO бүтэц.
 Стек заагч ба урвуу MIPS стек.
 Push
 Pop
 Run-time stack
 MIPS санах ойн text сегментүүд.
[www.cdeq.mn/hw200]