Проширени приручник који садржи ствари које би требале да се знају за рад задатака из арма на клк из уоара, а нису на чит-шиту Чит-шит какав ће бити на испиту се поже видети на: https://alas.matf.bg.ac.rs/~mi25067/subjects/uoar/primer2/cheatsheet.html Прво погледати материјал какав је на испиту па су ствари овде додатне Јер арм при дељењу не чува вредност остатка најбољи начин рачунања остатка је какав следи udiv w2, w0, w1 //w2 = w0 / w1 sdiv w2, w0, w1 //w2 = w0 / w1 udiv се користи за неозначено дељење, а sdiv за означено дељење msub w3, w1, w2, w0 //w3 = w0 - (w1*w2) Сада нам је остатак при дељењу бројева у регистрима w0 и w1 у регистру w3 У арму су регистри од w0 до w30, односно x0 до х30 користимо до 15, остали су за друге сврхе које нам нису нужно потребне за клк Када користимо вредности од осам бајта користимио х w је за 4 бајта и мање и за учитавање мањих података у w регистре морамо да водимо рачуна о две ствари Ако је податак од једног бајта користимо LDRB за учитавање Ако је податак од два бајта користимо LDRH за учитавање LDRSB и LDRSH се користе за једнобајтне, односно двобајтне вредности ако желимо и знак да учитамо То нам је корисно за нумеричке вредности, а за карактере на пример то не желимо да радимо Обратити пажњу на то да ли је у питању signed или unsigned вредност при вршењу поређења и користити адекватан скок: Означене за нормалне (signed) или неозначене за unsigned За означене су скокови b.lt // < b.le // <= b.gt // > b.ge // >= За неозначене су скокови b.lo // < b.ls // <= b.hi // > b.hs // >= Ако пишемо функцију која не позива ни једну другу функцију не морамо да се бавимо са стеком Иначе морамо да користимо стек чак и ако не чувамо ништа из регистара јер може да настане проблем при враћању из позване функције (У чит шиту је део о стеку Почетак функције и Крај функције) Када нам је важно да чувамо нешто из регистара након извршавања неке функције морамо да урадимо и SUB SP, SP, # Где одвајамо први већи или једнак број дељив са 16 који нам је број бајтова колико чувамо на стек (нпр. одвајамо 32 ако чувамо две осмобајтне и 2 четворобајтне вредности и укупно 24 бајта користимо) Вредности чувамо на стек тако што проширимо стек оним одузимањем стек поинтера за толико колико нам је потребно меморије на стеку Одузимамо јер стек расте на доле и онда прву вредност чувамо на стек поинтер и толико навише (сваки пут за толико колико нам предходна вредност заузима бајтова) Пример у којем чувамо неки четворобајтни број са w0, адресу са x1, карактере са w2, w3 и w4 SP <----- смер у ком расте стек FP _______________________________________ | w0 | x1 |w2|w3|w4| | | 4b | 8b |1b|1b|1b| | |_____________________________________| STP FP, LR, [SP, #-16]! MOV FP, SP SUB SP, SP, #16 //јер нам је потребно 15 бајтова одвајамо први број већи једнак од њега који је дељив са 16 str w0, [sp] //Чувамо на почетак стека и онда први бајт ће бити на sp, други на sp + 1, итд. str x1, [sp, #4] //Овако означавамо да учитавамо на адресу sp + 4 strb w2, [sp, #12] //Сада смо повећали за осам у односу на претходни офсет јер нам је претходна додатних осам бајтова strb w3, [sp, #13] //Као што видимо за карактере користимо strb јер чувамо само један (најдоњи бајт) са регистара Ово радимо јер арм нема као интел одвојене ознаке за једнобајтне и двобајтне регистре и зато да би рачунар знао да чувамо односно учитавамо једнобајтну вредност са четворобајтног регистара strb w4, [sp, #14] Учитали би смо аналогно ldr w0, [sp] ldr x1, [sp, #4] ldrb w2, [sp, #12] ldrb w3, [sp, #13] ldrb w4, [sp, #14] Треба обратити пажњу да функција коју би смо евентуално позвали враћа вредност на на w0 или x0 па је добра пракса да након позива функције пребацимо вредност са тог регистра на неки виши ако планирамо нешто са стека да учитамо у тај регистар Ово је само пример, како ради, али лоша пракса не пожељно на неким системима је да стављамо осмобајтне на адресе не дељиве са осам и четворобајтне на адресе не дељиве са 4 зато прати следеће: w вредности стављај на офсет дељив са 4. x вредности стављај на офсет дељив са 8. sp увек држи поравнат на 16 пре bl. Када баратамо нешто са неким стрингом итерирмо кроз њега до краја тако што проверимо са cmp w5, #0 за неки карактер који смо учитали на w5 и ако јесте нумеричка нула значи да је у питању крај стринга Када стављамо неко слово по жељи у неки регистар не морамо да знамо аскии вредност карактера већ можемо да урадимо као за нумеричку вредност али уз употребу апострофа mov w5, #'s' Неке ствари на које треба обратити пажњу са низовима: Када итерирамо кроз низ четворобајтних вредности и x0 је адреса почетка низа, а w1 је индекс учитавамо то у регистар са ldr w2, [x0, x1, lsl 2] Док је део x0, x1 јасан lsl 2 је леви шифт од w1 јер рачунар не зна које су величине чланова низа па да не би смо итерирали тако што индекс сабирамо са 4 ми урадимо леви шифт за 2 од индекса ту и то има исти ефекат као w1 * 4 и то значи да израз значи да узмемо са адресе x0 + x1 * 4 (ово је све јер је адреса бајт где почиње елемент па да нпр. учитамо у w2 са x0 + 1 учитали би смо доња три бајта првог елемента и први бајт другог, што не ваља) Аналогно радимо када је низ long, односно осмобајтних вредности само што је леви шифт 3 (исти ефекат као множење са 8) јер сваки елемент има осам бајтова и учитавамно у х регистар ldr x2, [x0, x1, lsl 3] Ми такође можемо да одвојимо неко место на стеку за неке променљиве и сачувамо те адресе ако су параметри функције показивачи на које уписује нешто и онда знамо да после позива учитамо вредности са те адресе стека Ако користиш x0–x15 и позовеш другу функцију, очекуј да су обрисани јер не мораш да знаш како друга функција ради, увек их чувај на стек ако их користиш после