SEN2201 · 10. hafta · Assembly Language

LC-3 assembly dili: direktifler, iki geçişli assembler, sembol tablosu

Etiketler, .ORIG/.FILL/.BLKW/.STRINGZ/.END, assembler'ın iki geçişi ve sembol tablosu; döngü, string işleme, alt program (JSR/RET) içeren tam programlar ve çıktıları.

assembly languageassemblerlabelopcodeoperandcommentpseudo-op (assembler directive).ORIG.FILL.BLKW.STRINGZ.ENDtwo-pass assemblysymbol tablelocation countersubroutineJSRRET

7-8. haftada makine kodunu elle yazdın: offset’leri saydın, bitleri yerleştirdin. Bu hem yavaş hem hataya açık. Assembly dili bu işi bir programa, assembler’a bırakır. Sen komutları isimleriyle (ADD, LD), adresleri etiketlerle (LOOP, COUNT) yazarsın; assembler adresleri hesaplar ve 0-1 dizisini üretir.

Bu hafta sınav soruları genelde şöyle: bir programın sembol tablosunu kur, bir satırın makine kodunu sembol tablosundan bul, programın ekrana ne yazdığını ya da bellekte neyi değiştirdiğini söyle, assembler hatasını bul.

Bir satırın yapısı

LOOP    ADD  R1, R1, #-1   ; sayaç azalt
AlanÖrnekZorunlu mu?
Etiket (label)LOOPhayır
Opcode ya da pseudo-opADDevet
OperandlarR1, R1, #-1komuta göre
Yorum; sayaç azalthayır

Sayılar: # ondalık (#-1, #48), x onaltılık (x3000, xFE00). Etiket bir adresin adıdır: LOOP, o satırın bellekteki adresini temsil eder.

TUZAK · opcode’u etiket yapmak. STR, ADD, BR, R3 gibi isimler etiket olamaz. Assembler satırın ilk kelimesi opcode ise onu komut sanar. “String” için STR yerine TEXT ya da MSG yaz.

Pseudo-op’lar (assembler directives)

Pseudo-op çalışma zamanında çalışan bir komut değildir; assembler’a verilen bir talimattır. Hepsi nokta ile başlar.

DirektifNe yapar?Kaç kelime?
.ORIG x3000Programın başlangıç adresi0
.FILL #4Bu konuma 4 değerini koy1
.FILL LOOPBu konuma LOOP’un adresini koy1
.BLKW 33 kelimelik boş yer ayır3
.STRINGZ "Hi"Her karakter bir kelime, sonda x0000uzunluk + 1 = 3
.ENDKaynak kodun sonu0

.END programın durduğu yer değildir. Program HALT ile durur; .END sadece assembler’a “bundan sonrası kaynak değil” der.

İki geçişli assembler

Sorun: LD R1, COUNT satırına geldiğinde COUNT daha aşağıda tanımlanıyor olabilir. Offset’i hesaplamak için COUNT’un adresi lazım. Buna ileri referans (forward reference) denir.

Çözüm: programı iki kez oku.

  1. Birinci geçiş: hiçbir şeyi çevirme. Bir konum sayacı (location counter) tut: .ORIG ile başlat, her komut ve .FILL için 1, .BLKW n için n, .STRINGZ için uzunluk + 1 artır. Etiketli her satırın adresini sembol tablosuna yaz.
  2. İkinci geçiş: her satırı makine koduna çevir. Bir etiket kullanıldığında adresini sembol tablosundan al, offset’i hesapla.

Çözümlü örnek: sembol tablosu

        .ORIG x3000
        LEA  R0, MSG        ; x3000
        PUTS                ; x3001
        LD   R1, COUNT      ; x3002
LOOP    ADD  R1, R1, #-1    ; x3003
        BRp  LOOP           ; x3004
        HALT                ; x3005
COUNT   .FILL #4            ; x3006
MSG     .STRINGZ "Hello"    ; x3007 - x300C (6 kelime)
BUF     .BLKW 3             ; x300D - x300F
END1    .FILL x0041         ; x3010
        .END
SembolAdres
LOOPx3003
COUNTx3006
MSGx3007
BUFx300D
END1x3010

İkinci geçişin ürettiği kodun bir kısmı:

x3000  xE006   LEA R0, MSG      offset = x3007 - x3001 = 6
x3001  xF022   PUTS
x3002  x2203   LD  R1, COUNT    offset = x3006 - x3003 = 3
x3003  x127F   ADD R1, R1, #-1
x3004  x03FE   BRp LOOP         offset = x3003 - x3005 = -2
x3005  xF025   HALT
x3006  x0004
x3007  x0048 x0065 x006C x006C x006F x0000   "Hello"

Program çalışınca ekrana Hello yazar, sonra R1’i 4’ten 0’a kadar sayar ve durur.

Assembler hataları

SatırHata
ADD R1, R1, #20imm5 -16..15 dışında
LD R1, FAR (FAR 300 kelime ötede)PCoffset9 -256..255 dışında
BRz DONEEtanımsız etiket (yazım hatası)
LOOP iki kez tanımlıaynı etiket iki adres
STR .FILL #1opcode etiket olarak kullanılamaz

Programlama kalıpları

Bir karakteri aramak

Karakteri karşılaştırmanın yolu: negatifini bir sabite koy, topla, sonuç sıfırsa eşittir.

        .ORIG x3000
        AND  R2, R2, #0     ; R2 = sayaç
        LEA  R1, TEXT       ; R1 = string pointer
        LD   R4, NEGT       ; R4 = -'t'
NEXT    LDR  R3, R1, #0     ; R3 = *R1
        BRz  DONE           ; null → bitti
        ADD  R5, R3, R4     ; R5 = karakter - 't'
        BRnp SKIP           ; eşit değil → atla
        ADD  R2, R2, #1     ; eşit → say
SKIP    ADD  R1, R1, #1     ; sonraki karakter
        BRnzp NEXT
DONE    LD   R0, ZERO
        ADD  R0, R0, R2     ; sayıyı ASCII rakama çevir
        OUT
        HALT
NEGT    .FILL #-116         ; 't' = 116
ZERO    .FILL x30           ; '0'
TEXT    .STRINGZ "test it"
        .END
3

Sayaç 9’u geçerse bu yöntem tek rakam basamaz; sınav soruları bu yüzden küçük sayılarla gelir.

Klavyeden oku, işle, yaz

        .ORIG x3000
        LD   R2, NEGLF      ; R2 = -10 (satır sonu)
READ    GETC                ; R0 = karakter
        ADD  R3, R0, R2
        BRz  STOP           ; Enter → dur
        LD   R4, MASK
        AND  R0, R0, R4     ; büyük harfe çevir
        OUT
        BRnzp READ
STOP    HALT
NEGLF   .FILL #-10
MASK    .FILL xDF
        .END

Girdi bau ve Enter:

BAU

Alt programlar: JSR ve RET

Aynı kodu birçok yerde kullanmak için alt program (subroutine) yazılır.

  • JSR ETIKET: R7 ← PC (dönüş adresi), PC ← ETIKET. Offset 11 bit (-1024..1023).
  • JSRR R3: aynı şey, hedef register’da.
  • RET: PC ← R7.
        .ORIG x3000
        LD   R2, TIMES
AGAIN   JSR  PRINT
        ADD  R2, R2, #-1
        BRp  AGAIN
        HALT
PRINT   ST   R7, SAVE7      ; dönüş adresini sakla
        LEA  R0, TXT
        PUTS                ; TRAP: R7'yi ezer!
        LD   R7, SAVE7      ; dönüş adresini geri al
        RET
TIMES   .FILL #3
SAVE7   .BLKW 1
TXT     .STRINGZ "ab"
        .END
ababab

TUZAK · R7’yi kaydetmemek. Alt programın içinde bir TRAP ya da başka bir JSR varsa R7 ezilir. Kaydetmezsen RET yanlış yere döner. Ayrıca alt programın bozduğu register’ları da kaydetmek iyi alışkanlıktır (callee-save). C’de bu iş çalışma yığınıyla (runtime stack) yapılır (12. hafta).

Sık yapılan hatalar

Yanlış düşünceDoğrusu
.STRINGZ "Hi" 2 kelime3: sonda x0000 var
.BLKW 3 1 kelime3 kelime
.END programı durdururHALT durdurur; .END kaynak sonu
.ORIG bir kelime kaplarHiç kaplamaz
Tek geçiş yeterİleri referanslar için iki geçiş
Offset = etiket - satır adresietiket - (satır adresi + 1)
ADD R1, R1, #20 geçerliimm5 en fazla 15
TRAP R7’yi korurR7’ye dönüş adresi yazar

Kendini test et

Sınavdaki gibi İngilizce sorular. Önce kâğıt kalemle çöz, sonra cevabı aç.

Soru 1kolay

How many memory locations does MSG .STRINGZ "Hello" occupy?

Cevabı göster
6

Her karakter bir kelimeye (16 bit) yazılır: H, e, l, l, o = 5. Sonuna bir x0000 (null terminator) eklenir. Toplam 6. Genel kural: uzunluk + 1.

Soru 2orta

Build the symbol table for this program.

        .ORIG x3000
        LEA  R0, MSG
        PUTS
        LD   R1, COUNT
LOOP    ADD  R1, R1, #-1
        BRp  LOOP
        HALT
COUNT   .FILL #4
MSG     .STRINGZ "Hello"
BUF     .BLKW 3
END1    .FILL x0041
        .END
Cevabı göster
LOOP x3003, COUNT x3006, MSG x3007, BUF x300D, END1 x3010

Konum sayacı x3000'den başlar, her komut ve .FILL 1 yer kaplar. LEA x3000, PUTS x3001, LD x3002, LOOP x3003, BRp x3004, HALT x3005, COUNT x3006, MSG x3007.
.STRINGZ "Hello" 6 yer: x3007-x300C. BUF x300D, .BLKW 3 → x300D-x300F. END1 x3010.

Soru 3orta

Using the symbol table above, what is the machine code of LD R1, COUNT at address x3002?

Cevabı göster
x2203

offset = COUNT - (x3002 + 1) = x3006 - x3003 = 3. 0010 001 000000011 = x2203. Assembler bu hesabı ikinci geçişte sembol tablosuyla yapar.

Soru 4kolay

Why does the LC-3 assembler make two passes over the program?

Cevabı göster
To resolve forward references: labels used before they are defined

LD R1, COUNT satırına gelindiğinde COUNT henüz tanımlanmamış olabilir (aşağıda). Birinci geçiş sadece adresleri sayar ve sembol tablosunu kurar. İkinci geçiş her satırı makine koduna çevirir; artık her etiketin adresi bellidir.

Soru 5kolay

What is the difference between an instruction such as ADD and a pseudo-op such as .FILL?

Cevabı göster
ADD becomes a machine instruction executed at run time; .FILL is a directive to the assembler

Pseudo-op (assembler directive) çalışma zamanında çalışmaz, bir opcode'u yoktur. Assembler'a ne yapacağını söyler: .ORIG başlangıç adresi, .FILL bir değer koy, .BLKW yer ayır, .STRINGZ string koy, .END kaynak bitti.

Soru 6orta

Which of these lines generate no memory words at all: .ORIG x3000, .FILL #0, .BLKW 1, .END, HALT?

Cevabı göster
.ORIG and .END

.ORIG sadece konum sayacını ayarlar, .END sadece kaynağın bittiğini söyler. .FILL #0 ve .BLKW 1 birer kelime (x0000) ayırır, HALT bir komut (xF025) üretir.

Soru 7orta

The assembler reports an error for ADD R1, R1, #20. Why, and how can you add 20 to R1?

Cevabı göster
imm5 range is -16..15; load 20 from a .FILL or use two ADDs

imm5 5 bitlik 2's complement'tir, 20 sığmaz. Çözüm: ADD R1, R1, #10 iki kez, ya da TWENTY .FILL #20 tanımla, LD R2, TWENTY, ADD R1, R1, R2.

Soru 8orta

What is printed by this program?

        .ORIG x3000
        AND  R2, R2, #0
        LEA  R1, TEXT
        LD   R4, NEGT
NEXT    LDR  R3, R1, #0
        BRz  DONE
        ADD  R5, R3, R4
        BRnp SKIP
        ADD  R2, R2, #1
SKIP    ADD  R1, R1, #1
        BRnzp NEXT
DONE    LD   R0, ZERO
        ADD  R0, R0, R2
        OUT
        HALT
NEGT    .FILL #-116
ZERO    .FILL x30
TEXT    .STRINGZ "test it"
        .END
Cevabı göster
3

-116 = -'t' (ASCII 't' = 116). Her karakter için R5 = karakter - 't'; sıfırsa 't' bulundu, R2 artar. Null (0) gelince döngü biter.
"test it" içinde 3 tane 't' var. R0 = x30 + 3 = x33 = '3', OUT basar.

Soru 9kolay

What is the sum stored at TOTAL?

        AND  R0, R0, #0
        LEA  R1, NUMS
        LD   R2, N
LOOP    LDR  R3, R1, #0
        ADD  R0, R0, R3
        ADD  R1, R1, #1
        ADD  R2, R2, #-1
        BRp  LOOP
        ST   R0, TOTAL
        HALT
N       .FILL #4
NUMS    .FILL #12
        .FILL #-5
        .FILL #30
        .FILL #-7
TOTAL   .BLKW 1
Cevabı göster
30

Sayaçlı döngü 4 elemanı toplar: 12 + (-5) + 30 + (-7) = 30. R1 pointer (LEA ile dizinin başı), her turda bir sonraki kelimeye ilerler.

Soru 10zor

What is printed by this program? Why does PRINT save R7?

        LD   R2, TIMES
AGAIN   JSR  PRINT
        ADD  R2, R2, #-1
        BRp  AGAIN
        HALT
PRINT   ST   R7, SAVE7
        LEA  R0, TXT
        PUTS
        LD   R7, SAVE7
        RET
TIMES   .FILL #3
SAVE7   .BLKW 1
TXT     .STRINGZ "ab"
Cevabı göster
ababab; PUTS (a TRAP) overwrites R7

JSR dönüş adresini R7'ye yazar. PRINT içindeki PUTS bir TRAP'tir ve o da R7'yi ezer. R7 kaydedilmeseydi RET yanlış yere (PUTS'tan sonraki satıra) dönerdi ve program sonsuz döngüye girerdi. Kaydedilip geri yüklendiği için alt program 3 kez çağrılır: ababab.

Soru 11orta

A program reads characters with GETC until the newline character (ASCII 10), ANDs each with xDF and prints it. What is printed for the input bau followed by Enter?

Cevabı göster
BAU

AND xDF bit 5'i temizler: küçük harf büyük harfe döner. 'b' x62 → x42 'B', 'a' x61 → x41 'A', 'u' x75 → x55 'U'. Satır sonu (10) gelince döngü biter. Dikkat: rakamlar da bu maskeden etkilenir ('3' x33 → x13), bu yüzden sadece harflerde kullanılır.

Soru 12zor

Why can't you name a label STR or ADD in LC-3 assembly?

Cevabı göster
They are opcodes (reserved words)

Assembler bir satırın ilk kelimesine bakar: opcode ya da pseudo-op ise komut, değilse etikettir. STR ve ADD opcode olduğu için etiket olarak okunmaz ve satır yanlış çözülür. Etiketler harfle başlar, opcode, register adı (R0-R7) ya da sayı olamaz.

Doğrulama: Tüm sembol tabloları, makine kodları, assembler hataları ve program çıktıları kendi iki geçişli LC-3 assembler + simülatörümüzle üretildi (verify/SEN2201/lc3.mjs, verify/SEN2201/10.mjs).

Deftere not kartı

Satır: [ETİKET] OPCODE OPERANDLAR [; yorum] .ORIG x3000 başlangıç | .END kaynak sonu (ikisi de bellek kaplamaz) .FILL değer -> 1 kelime | .BLKW n -> n kelime (0) | .STRINGZ "abc" -> 4 kelime (sonda x0000) Pseudo-op = assembler'a emir, çalışmaz, opcode'u yok Geçiş 1: konum sayacıyla etiketleri say -> SEMBOL TABLOSU Geçiş 2: her satırı makine koduna çevir (offset = etiket - (adres+1)) Neden 2 geçiş: ileri referanslar (etiket aşağıda tanımlı) Hatalar: imm5 dışı (#20), offset9 dışı (çok uzak etiket), tanımsız etiket, opcode'u etiket yapmak Sabit > 15 lazım: X .FILL #20 + LD Karakter karşılaştır: .FILL #-'c' ile topla, BRz JSR ETIKET: R7 <- PC, PC <- etiket | RET: PC <- R7 Alt program içinde TRAP/JSR varsa R7'yi kaydet (ST R7, SAVE7 ... LD R7, SAVE7)