2016-12-03 5 views
0

私は与えられた数をLC3の異なるベースに変換する必要がある割り当てに取り組んでいます。これを行うには、除算を使用する必要があります。また、同じことを行った代入がある間に、この除算アルゴリズムは異なります。トラップがLC3の不正なベクタ番号で実行されました

この割り当てでは、拡張除算を使用することが予想されます。

32ビットの数値を指定すると、最初の16ビットをメモリアドレス(高分子と呼ばれます)に格納し、最後の16ビット(低分子)を別の1ビットに、除数を別の16ビットビット数を別のビット数に変換します。だから、サブルーチンに、番号が異なるレジスタにメモリからフェッチされると、次のようなアルゴリズムが働くだろう:

  • 高い分子および低分子のためのレジスタがあれば、高ビットように(後左にシフトされている両方(左端)が1である場合、それは高分子の下位ビットに渡される。これはシフトされているので、ゼロでなければならない。)
  • 高い分子が除数と比較される。それ以上であれば、除数を減算して低分子の下位ビットを設定します。そうでない場合は、何もしないでください(最終的にシフトを続けると、結果は大きくなります)
  • シフトを繰り返して、分子の下位ビット(右端)を設定して16回確認してください。
  • 最後に、高い分子は除算の残りの部分を保持し、分子が小さいレジスタは商を保持します

わかりやすくするために、私たちの指導者は0を高分子として使用しています。

  • まず、私は5の.BLKWを宣言し、名前の引数リスト、すべての引数が
  • PRINTサブルーチンを格納されます::だから、アルゴリズムを満たすために、私は、次の手順を思い付いた私は宣言するすべてのST演算は、作業用レジスタの値をサブルーチンで使用されるものとは別の値に保つために、ARGLISTのアドレスをレジスタにロードします。レジスタには低分子が格納され、インクリメントは高分子0)and divisor>次に、BUFFERとDIGITSのポインタにロードして、指定されたベースに変換した結果を格納します。次に、DIVIDEサブルーチンは
  • DIVIDEサブルーチンと呼ばれます:私はARGLISTのアドレスをレジスタにロードし(割り当て命令に従ってR6)、値を準備するために必要なレジスタにロードし、インクリメントし、 (低い分子の高いビットを得るためにx0080でマスキングが行われます)、DVRが高分子以下で繰り返されるたびに減算します。次に、商と余りが格納され、R6が指し示されている場所に格納されます(もちろん、次のレコードに進むためにインクリメントします)。
  • PRINTに戻って、R2とR3にロードします。 R7が指している値から、ARGLISTをポイントするので、サブルーチンは割り当て2と同様に続行します。
  • バッファに格納された全体が発生したとき、 「更新」に引数リストの先頭に商に低分子とのポイントは次の反復(次の除算)以下

の準備ができなければ、私が持っている完全なコードは、これまでのところです:

.ORIG x3000 
    LEA R0, MPROMPT 
    TRAP x22 
LOOP 
    JSR GETDEC  ;Input an unsigned (decimal) integer 
    ADD R0, R0, #0 ;Exit if the input integer is 0 
    BRZ EXIT 

    JSR NEWLN  ;Move cursor to the start of a new line 
    AND R1, R1, #0 ;R1 = 10 (output base 10 DECIMAL) 
    ADD R1, R1, #10 
    JSR PRINT  ;Print the integer in decimal 

    JSR NEWLN  ;Move cursor to the start of a new line 
    AND R1, R1, #0 ;R1 = 2 (output base 2 BINARY) 
    ADD R1, R1, #2 
    JSR PRINT  ;Print the integer in binary 

    JSR NEWLN  ;Move cursor to the start of a new line 
    AND R1, R1, #0 ;R1 = 8 (output base 8 OCTAL) 
    ADD R1, R1, #8 
    JSR PRINT  ;Print the integer in octal 

    JSR NEWLN  ;Move cursor to the start of a new line 
    AND R1, R1, #0 ;R1 = 16 (output base 16 HEXADECIMAL) 
    ADD R1, R1, #15 
    ADD R1, R1, #1 
    JSR PRINT  ;Print the integer in hexadecimal 

    JSR NEWLN  ;Move cursor to the start of a new line 

    BRNZP LOOP 
EXIT    ;Loop exit point 
    TRAP x25  ;HALT program execution 
MPROMPT .STRINGZ "Enter a sequence of unsigned integer values\nEnter 0 To Quit\n" 

;Subroutine NEWLN************************************************************* 
;Advances the console cursor to the start of a new line 
NEWLN 
    ST R7, NEW7 ;Save working registers 
    ST R0, NEW0 

    LD R0, NL  ;Output a newline character 
    TRAP x21 

    LD R0, NEW0 ;Restore working registers 
    LD R7, NEW7 
    RET   ;Return 
;Data 
NL .FILL x000A ;Newline character 
NEW0 .BLKW 1 ;Save area - R0 
NEW7 .BLKW 1 ;Save area - R7 

;Subroutine GETDEC************************************************************ 
;Inputs an unsigned integer typed at the console in decimal format 
;The input value is returned in R0 
GETDEC 
    ;Save Values of ALL Registers that don't need to change 
    ST R1, GET1 
    ST R2, GET2 
    ST R3, GET3 
    ST R4, GET4 
    ST R5, GET5 
    ST R6, GET6 
    ST R7, GET7 ;Save R7 to be able to return to main 

    AND R3, R3, #0 ;Prepare a value 
    LEA R0, GPROMPT 
    TRAP x22 
GETDKEY 
    TRAP x20  ;To input a keystroke 
    ADD R2, R0, #-10 ;Subtract new keystroke by 10 (new line, or enter) 
    BRZ GFINIS  ;If R2 is 0 we just pressed enter, so we break out 
    TRAP x21  ;Echo keystroke  
    ADD R2, R0, #0 ;Get the number back 
    AND R2, R2, #15 ;We mask to only get the first four bits 
    ADD R3, R3, R3 ;1st addition: x + x = 2x 
    ADD R4, R3, #0 ;Store the 2x 
    ADD R3, R3, R3 ;2nd addition: 2x + 2x = 4x 
    ADD R3, R3, R3 ;3rd addition: 4x + 4x = 8x 
    ADD R3, R3, R4 ;4th addition: 8x + 2x = 10x 
    ADD R3, R3, R2 ;10x + new number 
    BRNZP GETDKEY  ;Go back to get next number 
GFINIS 
    ADD R0, R3, #0 ;Put number into R0 

    ;Restore the values of registers that don't need change 
    LD R1, GET1 
    LD R2, GET2 
    LD R3, GET3 
    LD R4, GET4 
    LD R5, GET5 
    LD R6, GET6 
    LD R7, GET7 ;Get back the value of R7 
    RET 
;Data 
GPROMPT .STRINGZ "Enter an unsigned integer> " ;Input Prompt 
GET1 .BLKW 1 
GET2 .BLKW 1 
GET3 .BLKW 1 
GET4 .BLKW 1 
GET5 .BLKW 1 
GET6 .BLKW 1 
GET7 .BLKW 1 

;Subroutine PRINT************************************************************* 
;Displays an unsigned integer in any base up to 16, e.g. binary, octal, decimal 
;Parameters - R0: the integer - R1: the base 
PRINT 
    ST R0, PR0 
    ST R1, PR1 
    ST R2, PR2 
    ST R3, PR3 
    ST R4, PR4 
    ST R5, PR5 
    ST R6, PR6 
    ST R7, PR7 

    LEA R7, ARGLIST ;Point to ARGLIST to start populating the args 
    STR R0, R7, #0 ;Put R0 to be the low numerator 
    AND R0, R0, #0 ;R0 is not needed after this, so it is cleared 

    ADD R7, R7, #1 ;Go down on pointer once to store next arg 
    STR R0, R7, #0 ;Put R0, now x0000, to be the high numerator 

    ADD R7, R7, #1 
    STR R1, R7, #0 ;Store the base, R1, to be the DVR 
    ADD R7, R7, #1 ;Have R7 point to Quotient 

    LEA R6, BUFFER 
    AND R5, R5, #0 ;To make sure R5 is cleared 
    LEA R4, DIGITS ;Prepare pointer to the digits 
SDIV 
    JSR DIVIDE 

    LDR R2, R7, #0 ;Since the addresses should now be ready, 
       ;R7 would point to quotient, passed to R2 
    LDR R3, R7, #1 ;Pass remainder to R3 

    ADD R3, R3, R4 
    LDR R5, R3, #0 
    ADD R6, R6, #-1 ;Decrement to get to the next one 
    STR R5, R6, #0 ;Store number into buffer 

    LEA R7, ARGLIST ;Go back to ARGLIST to store new numerator 
    STR R2, R7, #0 
    ADD R7, R7, #3 ;Point to quotient 

    ADD R0, R2, #0 ;Pass quotient into R0 
    BRP SDIV  ;If number is at least 1, then divide again 

    ADD R0, R6, #0 ;If we got here, then we should have the converted number 
    TRAP x22  ;Last but not least we display 

    LD R0, PR0 
    LD R1, PR1 
    LD R2, PR2 
    LD R3, PR3 
    LD R4, PR4 
    LD R5, PR5 
    LD R6, PR6 
    LD R7, PR7 
    RET 
;Data 
DIGITS .STRINGZ "ABCDEF" ;Digits 
     .BLKW 18   ;Output Buffer 
BUFFER .FILL x0000   ;Null 
PR0 .BLKW 1 
PR1 .BLKW 1 
PR2 .BLKW 1 
PR3 .BLKW 1 
PR4 .BLKW 1 
PR5 .BLKW 1 
PR6 .BLKW 1 
PR7 .BLKW 1 

;Subroutine DIVIDE************************************************************ 
;Extended division is done here 
DIVIDE 
    ST R1, DIV1 
    ST R2, DIV2 
    ST R3, DIV3 
    ST R4, DIV4 
    ST R5, DIV5 
    ST R6, DIV6 
    ST R7, DIV7 

    LEA R6, ARGLIST ;Point straight to where arguments start 

    LDR R5, R6, #0 ;Load NUMLOW into R5 
    ADD R6, R6, #1 ;Go down one step in pointer 

    LDR R4, R6, #0 ;Load NUMHIGH into R4 
    ADD R6, R6, #1 ;Go down once more 

    LDR R3, R6, #0 ;Load DVR into R3 
    ADD R6, R6, #1 ;Go down yet once more to be ready when we 
       ;store results 

    LD R1, M8BIT ;Make R1 be equal to x0080 to get last bit 
       ;from NUMLOW 

    AND R2, R2, #0 ;Set R2 as counter to decrement with each 
    ADD R2, R2, #10 ;iteration 
    ADD R2, R2, #6 

ITER ADD R4, R4, R4 ;Shift NUMHIGH to the left once 
    AND R7, R5, R1 ;Masking. If R5[7] == 1, then R7 == x0080    
    BRNZ NOADD  ;(or positive) 

    ADD R4, R4, #1 ;If this happens then R5[7] was set, so we're 
       ;adding the bit that would be lost if R5 
       ;shifts left 

NOADD ADD R5, R5, R5 ;Shift NUMLOW to the left once 

    NOT R7, R3  ;Subtract NUMHIGH and DVR. If 0 or positive 
    ADD R7, R7, #1 ;then subtract and increment NUMLOW 
    ADD R7, R4, R7 
    BRN DECCNT  ;If negative then DVR is greater than NUMHIGH, 
       ;go straight to decrement the loop count 
    ADD R4, R7, #0 
    ADD R5, R5, #1 

DECCNT ADD R2, R2, #-1 
    BRP ITER  ;If count is positive, go back to ITER 

    STR R5, R6, #0 ;Store NUMLOW for the Quotient Address 
    ADD R6, R6, #1 ;Increment to store in the next one 
    STR R4, R6, #0 ;Store NUMHIGH for the Remainder Address 

    LD R1, DIV1 
    LD R2, DIV2 
    LD R3, DIV3 
    LD R4, DIV4 
    LD R5, DIV5 
    LD R6, DIV6 
    LD R7, DIV7 

    RET   ;Return 
;Data 
ARGLIST .BLKW 5  ;Here we will put the LOWNUM, HIGHNUM, 
       ;DVR, QUO, and REM 
M8BIT .FILL x0080    
DIV1 .BLKW 1 
DIV2 .BLKW 1 
DIV3 .BLKW 1 
DIV4 .BLKW 1 
DIV5 .BLKW 1 
DIV6 .BLKW 1 
DIV7 .BLKW 1 

    .END 

私はアルゴリズムが働くべきだと思うが、私はLC3上でそれを実行するように、私は次のエラーを取得:

A trap was executed with an illegal vector number 

をし、プロセッサが停止しています。再びDIVIDEサブルーチンを呼び出すために分岐する前に、右のだろう

ADD R0, R2, #0

:何らかの理由で、私はLC3に自分のコードをチェックしたときにそれが適切なこの行の後に消去されることを気づきました。

なぜこれが起こっていますか?私が知る限りでは、私はレジスタを適切に保存して復元しています(前回同様の問題があり、エラーを起こした.BLKWに保存していたと指摘していました)が、エラー持続する。何が誤動作しているのか、さらに必要な情報があれば誰にでも知らせてください。助けをありがとうございます。

答えて

0

解決済み。 2つの主なエラーがありました:

1)マスクを使用する必要はありませんでした。何かがあったとしても、レジスタは16ビットの値を保持するので、マスク自体が間違っていました。マスクを使用したい場合、より適切な値はx8000でしたが、これは実際にはRTIのオペコードであるため使用できません。私がしなければならなかったのは、低分子のレジスタであるR5を分岐計算に確実に入れることでした。それがnegativeだった場合、高いビットは明らかに1です!

2)これはプログラムを破っていたものです。 PRINT機能では、LEAR7を使用していました。これは、私が議論を指す責任があるこの登録簿を保持していたことを意味します。しかし、この後のいくつかの行は、私がJSRを呼び出す:

JSR DIVIDE

私は、このようなジャンプが発生した場合、内部で通常のプログラム実行に復帰できるようにするために必要なPCの値がレジスタ内に格納されていることを認識することができませんでした。どこ? R7。だから、最初とDIVIDEの終わりに、私はPRINTに戻った時に、R7の値を復元するためにSTLDを持っていた場合でも、それは次の命令のアドレス、ARGLISTへのポインタではなくなっているだろう。プログラムが正常に動作するために必要なのは、シンプルなLEAを追加し、3を商と剰余を指すように追加し、ポインタの操作を少し下げて更新された低分子を格納することでした。全体として、DIVIDEコールの直後のコードは次のようになります。

SDIV 
    JSR DIVIDE 

    LEA R7, ARGLIST 
    ADD R7, R7, #3 

    LDR R2, R7, #0 ;Since the addresses should now be ready, 
        ;R7 would point to quotient, passed to R2 
    LDR R3, R7, #1 ;Pass remainder to R3 

    ADD R3, R3, R4 
    LDR R5, R3, #0 
    ADD R6, R6, #-1 ;Decrement to get to the next one 
    STR R5, R6, #0 ;Store number into buffer 

    LEA R7, ARGLIST ;Go back to ARGLIST to store new numerator 
    STR R2, R7, #0 

    ADD R0, R2, #0 ;Pass quotient into R0 
    BRP SDIV  ;If number is at least 1, then divide again 

    ADD R0, R6, #0 ;If we got here, then we should have the converted number 
    TRAP x22  ;Last but not least we display 
関連する問題