Язык сборки LC3: пропуск вызова функции - PullRequest
1 голос
/ 20 января 2020

Я пишу программу на LC3, которая читает файл целых чисел, возводит в квадрат каждый элемент и складывает их квадраты. Мне нужна часть «возведения в квадрат», чтобы быть в функции, но в то время как l oop вызов моей функции полностью пропущен. Так что я получаю только те суммы в файле, которые не суммируются в первую очередь. Любая помощь приветствуется, спасибо!

; Program to calculate Euclidian sum of numbers stored at location x4000
;
.ORIG x3000
LD R1,a     ;first element address
LD R2,zero  ;ans -> R2 initialized to 0



;while (R1 isn't zero)

LOOP: LDR R4,R1,#0  ;element -> R4
      ADD R4,R4,-1  
      BRn DONE      ;if R1 < 0, condition fails

;loop body
LDR R4,R1,#0    ;element ->R4
LDR R5,R1,#0    ;counter
JSR SQUARE  
ADD R2,R2,R4    ;ans = ans + element
ADD R1,R1,#1    ;prepare for next element

BR LOOP     ;another iteration


ST R2,ans   ;result to ans

;
TRAP x25    ;exit

SQUARE
    ADD R4,R5,#0    ;R4 <- multiplier
    AND R6,R6,#0    ;R3 <- 0, sq
;inner loop
AGAIN
    ADD R6,R6,R4    
    ADD R5,R5,#-1   ;decerement counter
    BRp AGAIN   ;check end of calculation
    RET

;
zero .FILL 0 
a    .FILL x4000    ;a has the address of first location
ans  .BLKW 1        ;reserve location for ans
DONE  HALT      ;halt
.END

1 Ответ

0 голосов
/ 30 января 2020

В вашей программе есть две ошибки.

Чтение из неправильного регистра после возврата

Давайте посмотрим на эту подпрограмму SQUARE:

SQUARE
    ADD R4,R5,#0    ;R4 <- multiplier
    AND R6,R6,#0    ;R3 <- 0, sq
;inner loop
AGAIN
    ADD R6,R6,R4    
    ADD R5,R5,#-1   ;decerement counter
    BRp AGAIN   ;check end of calculation
    RET

Вы не делаете здесь есть какие-либо комментарии о том, как должна быть вызвана подпрограмма или что она возвращает. Это затрудняет понимание того, что не так. Вот что вы должны написать выше этой подпрограммы:

; SQUARE subroutine
; Squares an integer value
;
; Parameters:
;     R5: Value to be squared
; Return value:
;     R6: Squared value
; Notes:
;     This subroutine tramples R4

Почему? Если вы пытаетесь отладить вызывающий код, сделать это гораздо проще, если вы знаете, как должна вызываться подпрограмма, и какие предположения вы сделали при ее написании. Например, вы можете внести изменения во внешнюю l oop, чтобы использовать R4 в качестве временной переменной, и не понять, почему это значение перезаписывается. (Если вы действительно хотите go лишнюю милю, также запишите, поддерживает ли подпрограмма нулевые или отрицательные значения в качестве аргумента.)

Теперь, когда у нас есть этот комментарий, проблема в основном коде ясна:

LDR R4,R1,#0    ;element ->R4
LDR R5,R1,#0    ;counter
JSR SQUARE  
ADD R2,R2,R4    ;ans = ans + element

Загружаем значение в квадрат в R5 и вызываем SQUARE. Затем SQUARE записывает квадратное значение в R6, и мы ... загружаем значение из R4. Это не правильно. Он должен загружаться из R6, а не из R4.

(В качестве дополнительной проблемы здесь LDR R4,R1,#0 не требуется, поскольку подпрограмма SQUARE игнорирует значение в R4. Еще одно преимущество комментирования вашего кода!)

Таким образом, мы можем исправить этот код следующим образом:

LDR R5,R1,#0    ;counter
JSR SQUARE  
ADD R2,R2,R6    ;ans = ans + element

DONE не сохраняет до ANS

Давайте посмотрим на внешнее условие l oop:

LOOP  LDR R4,R1,#0  ;element -> R4
      ADD R4,R4,-1  
      BRn DONE      ;if R1 < 0, condition fails

Таким образом, мы загружаемся с адреса, на который указывает R1, и проверяем, является ли значение меньше или равно нулю. (Кстати, комментарий неверный.)

Так что же такое DONE?

DONE  HALT      ;halt

Он немедленно останавливается, не сохраняя R2 для вашего результата!

Итак исправление состоит в том, чтобы переместить строку, которая хранится в R2, чтобы она запускалась после перехода в DONE.

DONE
    ST R2, ans
    HALT      ;halt

Вот полный список кодов фиксированной программы:

; Program to calculate Euclidian sum of numbers stored at location x4000
;
.ORIG x3000
LD R1,a     ;first element address
LD R2,zero  ;ans -> R2 initialized to 0



;while (R1 isn't zero)

LOOP
    LDR R4,R1,#0  ;element -> R4
    ADD R4,R4,-1  
    BRn DONE      ;if R1 < 0, condition fails

;loop body
    LDR R5,R1,#0    ;counter
    JSR SQUARE  
    ADD R2,R2,R6    ;ans = ans + element
    ADD R1,R1,#1    ;prepare for next element

    BR LOOP     ;another iteration

; SQUARE subroutine
; Squares an integer value
;
; Parameters:
;     R5: Value to be squared
; Return value:
;     R6: Squared value
; Notes:
;     This subroutine tramples R4
SQUARE
    ADD R4,R5,#0    ;R4 <- multiplier
    AND R6,R6,#0    ;R3 <- 0, sq
;inner loop
AGAIN
    ADD R6,R6,R4    
    ADD R5,R5,#-1   ;decerement counter
    BRp AGAIN   ;check end of calculation
    RET

;
zero .FILL 0 
a    .FILL x4000    ;a has the address of first location
ans  .BLKW 1        ;reserve location for ans
DONE
    ST R2, ans
    HALT      ;halt
.END

Вот как я тестировал фиксированную программу:

$ lc3sim -quiet prog_fixed.obj
   x0289  x0FFB                     BRNZP  TRAP_LOOP
Loaded "prog_fixed.obj" and set PC to x3000
(lc3sim) memory x4000 3
Wrote x0003 to address x4000.
(lc3sim) continue
   x0289  x0FFB                     BRNZP  TRAP_LOOP
(lc3sim) translate ans
Address ans has value x0009.
...