![]() |
Jupyter at Bryn Mawr College |
|
|
Public notebooks: /services/public/dblank / CS240 Computer Organization / 2015-Fall / Notes |
It can't. It is a deterministic computer with no means of reaching outside of itself.
%%python
## Algorithm for the iteration x = a * x % m
## Using Schrage's method
a = 7 ## the multplicative contants
m = (2 ** 15) - 1 ## modulus
x = 10 ## random seed
q = m // a
r = m % a
for i in range(20):
x = a * (x % q) - r * (x // q)
if x < 0:
x = x + m
print(x)
The LC-3 Assembly code:
Produces exactly the same numbers, in the same sequence.
What have ween seen so far:
Generally described as:
#include <stdio.h>
int main() {
printf("Hello, world!");
return 0;
}
%%file Test1.c
#include <stdio.h>
int main() {
printf("Testing 1, 2, 3...\n");
return 0;
}
Using the GNU C Compiler:
! gcc -o Test1 Test1.c
The current directory (called ".") isn't in your search PATH, so we have to give the path to it.
! ./Test1
NOTES:
#include <stdio.h>
int main(int argc, char **argv) {
printf("Hello World");
return 0;
}
// Old style:
void main() {
int x; // define and use variables
float f;
x = 1;
f = 3.2;
}
// Newer style:
void main() {
int x = 1; // define and use variables
float f = 3.2;
}
In C, you can have variables that work with memory addresses. These are called "pointers". They expose the underlying way the system creates ans uses variables.
Arrays are nothing more than arrays with a type, so that you can figure out how far apart items are in memory.
int x = 7;
int *px = &x;
%%file Pointers.c
#include <stdio.h>
int main(int argc, char **argv) {
int x = 7;
int *px = &x;
printf("x is: %d\n", x);
printf("px is: %d\n", *px);
}
!gcc -o Pointers Pointers.c
!./Pointers
int array[] = {1, 2, 3};
char *string = "This is a string";
char *sarray[] = {"Hello", "world"};
%%file Arrays.c
#include <stdio.h>
int main(int argc, char **argv) {
char *string = "This is a string\n";
char *sarray1[] = {"Hello", "world"};
printf(string);
printf(sarray1[0]);
}
!gcc -o Arrays Arrays.c
! ./Arrays
! objdump -D Test1
We will change the system path so that you can access the lc3 compiler. This adds the path /opt/lcc to the bash system search variable, PATH.
We use the %%shell
magic to indicate that this cell is a bash shell script:
%%shell
export PATH=/opt/lcc:$PATH
NOTE: as it is a one-liner, we could have also typed:
! export PATH=/opt/lcc:$PATH
The change to the PATH bash shell environment variable will be retained on subsequent calls in the shell.
%%shell
echo $PATH
#include <stdio.h>
/* A simple C program to test the LC-3 compiler */
void main() {
int a, b;
a = 5;
b = a * a + 3;
printf("Result = %d\n", b);
}
stdio.h is a "header" file that contains the signatures for the standard IO functions. These are defined in these ASM files:
%%file Testme.c
#include <stdio.h>
/* A simple C program to test the LC-3 compiler */
void main() {
int a, b;
a = 5;
b = a * a + 3;
printf("Result = %d\n", b);
}
We can now use the lcc
LC-3 C Compiler to compile the C source code into an executable (.obj file, in LC-3).
NOTE: you can also just do ! lcc -o Testme.obj Testme.c
%%shell
lcc -o Testme.obj Testme.c
When creating a executable, the C Compiler will first create an .asm
file from the C source:
%load Testme.asm
.Orig x3000
INIT_CODE
LEA R6, #-1
ADD R5, R6, #0
ADD R6, R6, R6
ADD R6, R6, R6
ADD R6, R6, R5
ADD R6, R6, #-1
ADD R5, R5, R5
ADD R5, R6, #0
LD R4, GLOBAL_DATA_POINTER
LD R7, GLOBAL_MAIN_POINTER
jsrr R7
HALT
GLOBAL_DATA_POINTER .FILL GLOBAL_DATA_START
GLOBAL_MAIN_POINTER .FILL main
;;;;;;;;;;;;;;;;;;;;;;;;;;;;main;;;;;;;;;;;;;;;;;;;;;;;;;;;;
main
ADD R6, R6, #-2
STR R7, R6, #0
ADD R6, R6, #-1
STR R5, R6, #0
ADD R5, R6, #-1
ADD R6, R6, #-2
ADD R7, R4, #15
ADD R7, R7, #2
ldr R7, R7, #0
str R7, R5, #0
ldr R7, R5, #0
ADD R6, R6, #-1
STR R0, R6, #0
ADD R0, R7, #0
ADD R6, R6, #-1
STR R1, R6, #0
ADD R6, R6, #-1
STR R7, R6, #0
AND R1, R1, #0
ADD R7, R7, #0
BRz L6
BRp L5
NOT R7, R7
ADD R7, R7, #1
L5
ADD R1, R1, R0
ADD R7, R7, #-1
BRnp L5
L6
LDR R7, R6, #0
ADD R6, R6, #1
ADD R7, R7, #0
BRzp L7
NOT R1, R1
ADD R1, R1, #1
L7
;bef epilogue x=1 y=0 z=7
ADD R7, R1, #0
LDR R1, R6, #0
ADD R6, R6, #1
LDR R0, R6, #0
ADD R6, R6, #1
;aft epilogue x=1 y=0 z=7
ADD R3, R4, #15
ADD R3, R3, #1
ldr R3, R3, #0
add R7, R7, R3
str R7, R5, #-1
ldr R7, R5, #-1
ADD R6, R6, #-1
STR R7, R6, #0
ADD R7, R4, #3
ADD R6, R6, #-1
STR R7, R6, #0
ADD R0, R4, #2
LDR R0, R0, #0
jsrr R0
lc3_L1_Testme
STR R7, R5, #3
ADD R6, R5, #1
LDR R5, R6, #0
ADD R6, R6, #1
LDR R7, R6, #0
ADD R6, R6, #1
RET
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; void scanf(const char *format, ...)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SCANF_PERCENT .FILL -37
SCANF_C .FILL -99
SCANF_D .FILL -100
SCANF_S .FILL -115
SCANF_0 .FILL -48
SCANF_9 .FILL -57
SCANF_MINUS .FILL -45
SCANF_BUF .BLKW 6
lc3_scanf
ADD R6, R6, #-2
STR R7, R6, #0
ADD R6, R6, #-1 ;save R5 = bp
STR R5, R6, #0
ADD R5, R6, #-1
ADD R6, R6, #-1 ;save R4 = gp
STR R4, R6, #0
ADD R5, R5, #4 ;cheating with the bp (no longer bp)
LDR R4, R5, #0 ;got addr of format string
SCANF_LOOP ;outer loop, R0=tmp register for use with GETC
;R2 holds either cur letter of format string or
;current addr to store a char, dec, or string
LDR R2, R4, #0
ADD R2, R2, #0 ;End of format string? (0x0000)
BRz SCANF_DONE
LD R1, SCANF_PERCENT
ADD R0, R2, #0
ADD R0, R0, R1
BRnp SCANF_MATCHCHAR ;% not found
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;% found!
ADD R4, R4, #1 ;R4 points to next char of format string
LDR R2, R4, #0
LD R1, SCANF_C
ADD R0, R2, #0 ;next char = c?
ADD R0, R0, R1
BRnp SCANF_CHECKD
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;%c found
ADD R5, R5, #1
LDR R2, R5, #0 ;R2 has addr for char to be read into
GETC
OUT
STR R0, R2, #0
ADD R4, R4, #1
BRnzp SCANF_LOOP
SCANF_CHECKD
;is it %d?
LD R1, SCANF_D
ADD R0, R2, #0
ADD R0, R0, R1
BRnp SCANF_STR
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;%d found
;consider using vars to store reg
;registers 0,1,2,3,7 available as tmp regs
ADD R6, R6, #-1 ;saving current ptr into format string
STR R4, R6, #0
;ADD R6, R6, #-7 ;making 7byte buffer for ascbin
;ADD R4, R6, #0 ;ptr into that buffer
LEA R4, SCANF_BUF
LD R2, SCANF_0
LD R1, SCANF_9
SCANF_SCANNUM
GETC
OUT
STR R0, R4, #0 ;Reading and storing typed char
ADD R0, R2, R0
BRZP SCANF_CHECKEDLOWER
LDR R0, R4, #0
LD R7, SCANF_MINUS
ADD R0, R0, R7
BRz SCANF_CHECKEDLOWER
LEA R0, SCANF_BUF
NOT R0, R0
ADD R0, R0, #1
ADD R0, R4, R0
BRz SCANF_SCANNUM ;buffer is empty and wrong char, go to error?
ADD R4, R4, #-1 ;fixme: need to save this char
BRnzp SCANF_NUMDONE
SCANF_CHECKEDLOWER
LDR R0, R4, #0
ADD R0, R1, R0
BRNZ SCANF_CHECKEDUPPER
LEA R0, SCANF_BUF
NOT R0, R0
ADD R0, R0, #1
ADD R0, R4, R0
BRz SCANF_SCANNUM ;buffer is empty and wrong char, go to error?
ADD R4, R4, #-1 ;fixme: need to save this char
BRnzp SCANF_NUMDONE
SCANF_CHECKEDUPPER
LEA R0, SCANF_BUF
ADD R0, R0, #5
NOT R0, R0
ADD R0, R0, #1
ADD R0, R4, R0
BRz SCANF_NUMDONE ;buffer is full
ADD R4, R4, #1
BRnzp SCANF_SCANNUM
SCANF_NUMDONE
;R4 points to last char entered in (ones digit)
;ADD R7, R6, #0 ;R7 points to the highest order digit
LEA R7, SCANF_BUF
LD R0, SCANF_MINUS
LD R1, SCANF_BUF
ADD R0, R0, R1
BRnp SCANF_NOTMINUS
ADD R7, R7, #1 ;fixme check for - -
SCANF_NOTMINUS
;STR R2, R6, #-1 ;psuedo stored -'0' on stack
AND R2, R2, #0 ;R2 acts as the acumulator
SCANF_CALC
LDR R0, R7, #0
;LDR R1, R6, #-1
LD R1, SCANF_0
ADD R0, R0, R1
ADD R2, R2, R0
NOT R1, R7
ADD R1, R1, #1
ADD R1, R4, R1
BRz SCANF_CALCDONE
;R2 = 10*R2
ADD R0, R2, #0
AND R1, R1, #0
ADD R1, R1, #9 ;R1 = counter
SCANF_MULLOOP
ADD R2, R2, R0
ADD R1, R1, #-1
BRnp SCANF_MULLOOP
ADD R7, R7, #1
BRnzp SCANF_CALC
SCANF_CALCDONE
LD R0, SCANF_MINUS
LD R1, SCANF_BUF
ADD R0, R0, R1
BRnp SCANF_NOTNEG
NOT R2, R2
ADD R2, R2, #1
SCANF_NOTNEG
ADD R5, R5, #1
LDR R0, R5, #0
STR R2, R0, #0 ;store decimal number into address
;ADD R6, R6, #7
LDR R4, R6, #0
ADD R6, R6, #1 ;restoring current ptr into format string
ADD R4, R4, #1 ;point to next element of format string
BRnzp SCANF_LOOP
SCANF_STR
LD R1, SCANF_S
ADD R0, R2, #0
ADD R0, R0, R1
BRnp SCANF_ERROR
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;%s found
ADD R6, R6, #-1 ;saving current ptr into format string
STR R4, R6, #0
ADD R5, R5, #1 ;getting starting addr of space for string to be read in
LDR R4, R5, #0
SCANSTRLOOP
GETC
OUT
STR R0, R4, #0 ;Reading and storing typed char
ADD R4, R4, #1
ADD R0, R0, #-10 ;End of string? Looking for CR (0x000A)
BRnp SCANSTRLOOP
SCANSTRDONE
AND R0, R0, #0 ;null terminate string
STR R0, R4, #-1
LDR R4, R6, #0 ;restore r4
ADD R6, R6, #1
ADD R4, R4, #1
BRnzp SCANF_LOOP
SCANF_MATCHCHAR
ADD R4, R4, #1
GETC
OUT
NOT R0, R0
ADD R0, R0, #1
ADD R0, R0, R2
BRz SCANF_LOOP
SCANF_ERROR
SCANF_DONE
LDR R4, R6, #0 ;restore R4
ADD R6, R6, #1
LDR R5, R6, #0 ;restore bp
ADD R6, R6, #1
LDR R7, R6, #0 ;restore ret addr
ADD R6, R6, #1
RET
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; void printf(const char *format, ...)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PRINTF_PERCENT .FILL -37
PRINTF_C .FILL -99
PRINTF_D .FILL -100
PRINTF_S .FILL -115
PRINTF_B .FILL -98
PRINTF_O .FILL -111
PRINTF_X .FILL -120
PRINTF_ASCII .FILL 48 ;postive ascii value of '0'
.FILL 49
.FILL 50
.FILL 51
.FILL 52
.FILL 53
.FILL 54
.FILL 55
.FILL 56
.FILL 57
.FILL 65 ;A
.FILL 66
.FILL 67
.FILL 68
.FILL 69
.FILL 70
PRINTF_MINUS .FILL 45
PRINTF_BUF .BLKW 18
lc3_printf
ADD R6, R6, #-2
STR R7, R6, #0 ;return address
ADD R6, R6, #-1
STR R5, R6, #0
ADD R5, R6, #-1
ADD R6, R6, #-1
STR R4, R6, #0
ADD R5, R5, #4 ;cheating with the bp (no longer bp)
LDR R4, R5, #0 ;got addr of format string
PRINTF_LOOP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
LDR R0, R4, #0
ADD R0, R0, #0 ;End of string? (0x0000)
BRz PRINTF_DONE
ADD R2, R0, #0
LD R1, PRINTF_PERCENT
ADD R2, R2, R1
BRnp PRINTF_CHAR
ADD R4, R4, #1
LDR R0, R4, #0
;is it %c?
ADD R2, R0, #0
LD R3, PRINTF_C
ADD R2, R2, R3
BRnp PRINTF_CHECKSTR
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;%c
ADD R5, R5, #1
LDR R0, R5, #0
PRINTF_CHAR
OUT
ADD R4, R4, #1
BRnzp PRINTF_LOOP
PRINTF_CHECKSTR
;is it %s?
ADD R2, R0, #0
LD R7, PRINTF_S
ADD R2, R2, R7
BRnp PRINTF_CHECKDEC
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;%s
ADD R5, R5, #1
LDR R0, R5, #0
PUTS
ADD R4, R4, #1
BRnzp PRINTF_LOOP
PRINTF_CHECKDEC
;is it %d?
ADD R2, R0, #0
LD R7, PRINTF_D
ADD R2, R2, R7
;BRnp PRINTF_ERROR
BRnp PRINTF_CHECKHEX
AND R2, R2, #0
ADD R2, R2, #-10 ;going to divide by 10 by using sub loop
BRnzp PRINTF_NUM
PRINTF_CHECKHEX
ADD R2, R0, #0
LD R7, PRINTF_X
ADD R2, R2, R7
BRnp PRINTF_CHECKOCT
AND R2, R2, #0
ADD R2, R2, #-16 ;going to divide by 10 by using sub loop
BRnzp PRINTF_NUM
PRINTF_CHECKOCT
ADD R2, R0, #0
LD R7, PRINTF_O
ADD R2, R2, R7
BRnp PRINTF_CHECKBIN
AND R2, R2, #0
ADD R2, R2, #-8 ;going to divide by 10 by using sub loop
BRnzp PRINTF_NUM
PRINTF_CHECKBIN
ADD R2, R0, #0
LD R7, PRINTF_B
ADD R2, R2, R7
BRnp PRINTF_ERROR
AND R2, R2, #0
ADD R2, R2, #-2 ;going to divide by 10 by using sub loop
;BRnzp PRINTF_NUM
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;%d
PRINTF_NUM
LEA R7, PRINTF_BUF
ADD R7, R7, #15
ADD R7, R7, #1
;AND R2, R2, #0
;ADD R2, R2, #-10 ;going to divide by 10 by using sub loop
ADD R5, R5, #1 ;acquire the binary number
LDR R0, R5, #0
ADD R0, R0, #0
BRzp PRINTF_DECPOS
NOT R0, R0 ;make num positive for sub loop
ADD R0, R0, #1
PRINTF_DECPOS
AND R3, R3, #0
ADD R3, R3, #-1
PRINTF_DIVLOOP
ADD R3, R3, #1 ;num/10
ADD R0, R0, R2 ;R0 = num % 10 - 10
BRzp PRINTF_DIVLOOP
ADD R3, R3, #0
BRz PRINTF_LASTDIGIT
;LD R1, PRINTF_ASCII
;ADD R1, R1, R0
;NOT R2, R2
;ADD R1, R1, R2
;ADD R1, R1, #1
;NOT R2, R2
;;;;;ADD R1, R1, #10
;STR R1, R7, #0
;ADD R7, R7, #-1 ;stored ascii value of one digit
LEA R1, PRINTF_ASCII
ADD R1, R1, R0
NOT R2, R2
ADD R1, R1, R2
ADD R1, R1, #1
NOT R2, R2
LDR R1, R1, #0
STR R1, R7, #0
ADD R7, R7, #-1 ;stored ascii value of one digit
ADD R0, R3, #0 ;num/10
BRnzp PRINTF_DECPOS
PRINTF_LASTDIGIT
;LD R1, PRINTF_ASCII
;ADD R1, R1, R0
;ADD R1, R1, #10
;STR R1, R7, #0
LEA R1, PRINTF_ASCII
ADD R1, R1, R0
NOT R2, R2
ADD R1, R1, R2
ADD R1, R1, #1
NOT R2, R2
LDR R1, R1, #0
STR R1, R7, #0 ;stored ascii value of highest order digit
LDR R0, R5, #0
ADD R0, R0, #0
BRzp PRINTF_DECSTRING
LD R0, PRINTF_MINUS ;num was negative
ADD R7, R7, #-1
STR R0, R7, #0 ;stored ascii value negative sign
PRINTF_DECSTRING ;print the calculated string
ADD R0, R7, #0
PUTS
ADD R4, R4, #1
BRnzp PRINTF_LOOP
PRINTF_ERROR
PRINTF_DONE
LDR R4, R6, #0 ;restore R4
ADD R6, R6, #1
LDR R5, R6, #0 ;restore bp
ADD R6, R6, #1
LDR R7, R6, #0 ;restore ret addr
ADD R6, R6, #1
RET
GLOBAL_DATA_START
L1_Testme .FILL lc3_L1_Testme
scanf .FILL lc3_scanf
printf .FILL lc3_printf
L4_Testme .STRINGZ "Result = %d\n"
L3_Testme .FILL #3
L2_Testme .FILL #5
.END
%exe
%%file Optimize.c
#include <stdio.h>
int main() {
printf("The answer is %d\n", 88/3);
return 0;
}
!lcc -o Optimize.obj Optimize.c
%include Optimize.asm
%exe
%load Optimize.asm
.Orig x3000
INIT_CODE
LEA R6, #-1
ADD R5, R6, #0
ADD R6, R6, R6
ADD R6, R6, R6
ADD R6, R6, R5
ADD R6, R6, #-1
ADD R5, R5, R5
ADD R5, R6, #0
LD R4, GLOBAL_DATA_POINTER
LD R7, GLOBAL_MAIN_POINTER
jsrr R7
HALT
GLOBAL_DATA_POINTER .FILL GLOBAL_DATA_START
GLOBAL_MAIN_POINTER .FILL main
;;;;;;;;;;;;;;;;;;;;;;;;;;;;main;;;;;;;;;;;;;;;;;;;;;;;;;;;;
main
ADD R6, R6, #-2
STR R7, R6, #0
ADD R6, R6, #-1
STR R5, R6, #0
ADD R5, R6, #-1
ADD R6, R6, #-1
ADD R7, R4, #4
ldr R7, R7, #0
ADD R6, R6, #-1
STR R7, R6, #0
ADD R7, R4, #5
ADD R6, R6, #-1
STR R7, R6, #0
ADD R0, R4, #2
LDR R0, R0, #0
jsrr R0
ADD R7, R4, #3
ldr R7, R7, #0
lc3_L1_Optimize
STR R7, R5, #3
ADD R6, R5, #1
LDR R5, R6, #0
ADD R6, R6, #1
LDR R7, R6, #0
ADD R6, R6, #1
RET
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; void scanf(const char *format, ...)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SCANF_PERCENT .FILL -37
SCANF_C .FILL -99
SCANF_D .FILL -100
SCANF_S .FILL -115
SCANF_0 .FILL -48
SCANF_9 .FILL -57
SCANF_MINUS .FILL -45
SCANF_BUF .BLKW 6
lc3_scanf
ADD R6, R6, #-2
STR R7, R6, #0
ADD R6, R6, #-1 ;save R5 = bp
STR R5, R6, #0
ADD R5, R6, #-1
ADD R6, R6, #-1 ;save R4 = gp
STR R4, R6, #0
ADD R5, R5, #4 ;cheating with the bp (no longer bp)
LDR R4, R5, #0 ;got addr of format string
SCANF_LOOP ;outer loop, R0=tmp register for use with GETC
;R2 holds either cur letter of format string or
;current addr to store a char, dec, or string
LDR R2, R4, #0
ADD R2, R2, #0 ;End of format string? (0x0000)
BRz SCANF_DONE
LD R1, SCANF_PERCENT
ADD R0, R2, #0
ADD R0, R0, R1
BRnp SCANF_MATCHCHAR ;% not found
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;% found!
ADD R4, R4, #1 ;R4 points to next char of format string
LDR R2, R4, #0
LD R1, SCANF_C
ADD R0, R2, #0 ;next char = c?
ADD R0, R0, R1
BRnp SCANF_CHECKD
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;%c found
ADD R5, R5, #1
LDR R2, R5, #0 ;R2 has addr for char to be read into
GETC
OUT
STR R0, R2, #0
ADD R4, R4, #1
BRnzp SCANF_LOOP
SCANF_CHECKD
;is it %d?
LD R1, SCANF_D
ADD R0, R2, #0
ADD R0, R0, R1
BRnp SCANF_STR
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;%d found
;consider using vars to store reg
;registers 0,1,2,3,7 available as tmp regs
ADD R6, R6, #-1 ;saving current ptr into format string
STR R4, R6, #0
;ADD R6, R6, #-7 ;making 7byte buffer for ascbin
;ADD R4, R6, #0 ;ptr into that buffer
LEA R4, SCANF_BUF
LD R2, SCANF_0
LD R1, SCANF_9
SCANF_SCANNUM
GETC
OUT
STR R0, R4, #0 ;Reading and storing typed char
ADD R0, R2, R0
BRZP SCANF_CHECKEDLOWER
LDR R0, R4, #0
LD R7, SCANF_MINUS
ADD R0, R0, R7
BRz SCANF_CHECKEDLOWER
LEA R0, SCANF_BUF
NOT R0, R0
ADD R0, R0, #1
ADD R0, R4, R0
BRz SCANF_SCANNUM ;buffer is empty and wrong char, go to error?
ADD R4, R4, #-1 ;fixme: need to save this char
BRnzp SCANF_NUMDONE
SCANF_CHECKEDLOWER
LDR R0, R4, #0
ADD R0, R1, R0
BRNZ SCANF_CHECKEDUPPER
LEA R0, SCANF_BUF
NOT R0, R0
ADD R0, R0, #1
ADD R0, R4, R0
BRz SCANF_SCANNUM ;buffer is empty and wrong char, go to error?
ADD R4, R4, #-1 ;fixme: need to save this char
BRnzp SCANF_NUMDONE
SCANF_CHECKEDUPPER
LEA R0, SCANF_BUF
ADD R0, R0, #5
NOT R0, R0
ADD R0, R0, #1
ADD R0, R4, R0
BRz SCANF_NUMDONE ;buffer is full
ADD R4, R4, #1
BRnzp SCANF_SCANNUM
SCANF_NUMDONE
;R4 points to last char entered in (ones digit)
;ADD R7, R6, #0 ;R7 points to the highest order digit
LEA R7, SCANF_BUF
LD R0, SCANF_MINUS
LD R1, SCANF_BUF
ADD R0, R0, R1
BRnp SCANF_NOTMINUS
ADD R7, R7, #1 ;fixme check for - -
SCANF_NOTMINUS
;STR R2, R6, #-1 ;psuedo stored -'0' on stack
AND R2, R2, #0 ;R2 acts as the acumulator
SCANF_CALC
LDR R0, R7, #0
;LDR R1, R6, #-1
LD R1, SCANF_0
ADD R0, R0, R1
ADD R2, R2, R0
NOT R1, R7
ADD R1, R1, #1
ADD R1, R4, R1
BRz SCANF_CALCDONE
;R2 = 10*R2
ADD R0, R2, #0
AND R1, R1, #0
ADD R1, R1, #9 ;R1 = counter
SCANF_MULLOOP
ADD R2, R2, R0
ADD R1, R1, #-1
BRnp SCANF_MULLOOP
ADD R7, R7, #1
BRnzp SCANF_CALC
SCANF_CALCDONE
LD R0, SCANF_MINUS
LD R1, SCANF_BUF
ADD R0, R0, R1
BRnp SCANF_NOTNEG
NOT R2, R2
ADD R2, R2, #1
SCANF_NOTNEG
ADD R5, R5, #1
LDR R0, R5, #0
STR R2, R0, #0 ;store decimal number into address
;ADD R6, R6, #7
LDR R4, R6, #0
ADD R6, R6, #1 ;restoring current ptr into format string
ADD R4, R4, #1 ;point to next element of format string
BRnzp SCANF_LOOP
SCANF_STR
LD R1, SCANF_S
ADD R0, R2, #0
ADD R0, R0, R1
BRnp SCANF_ERROR
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;%s found
ADD R6, R6, #-1 ;saving current ptr into format string
STR R4, R6, #0
ADD R5, R5, #1 ;getting starting addr of space for string to be read in
LDR R4, R5, #0
SCANSTRLOOP
GETC
OUT
STR R0, R4, #0 ;Reading and storing typed char
ADD R4, R4, #1
ADD R0, R0, #-10 ;End of string? Looking for CR (0x000A)
BRnp SCANSTRLOOP
SCANSTRDONE
AND R0, R0, #0 ;null terminate string
STR R0, R4, #-1
LDR R4, R6, #0 ;restore r4
ADD R6, R6, #1
ADD R4, R4, #1
BRnzp SCANF_LOOP
SCANF_MATCHCHAR
ADD R4, R4, #1
GETC
OUT
NOT R0, R0
ADD R0, R0, #1
ADD R0, R0, R2
BRz SCANF_LOOP
SCANF_ERROR
SCANF_DONE
LDR R4, R6, #0 ;restore R4
ADD R6, R6, #1
LDR R5, R6, #0 ;restore bp
ADD R6, R6, #1
LDR R7, R6, #0 ;restore ret addr
ADD R6, R6, #1
RET
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; void printf(const char *format, ...)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PRINTF_PERCENT .FILL -37
PRINTF_C .FILL -99
PRINTF_D .FILL -100
PRINTF_S .FILL -115
PRINTF_B .FILL -98
PRINTF_O .FILL -111
PRINTF_X .FILL -120
PRINTF_ASCII .FILL 48 ;postive ascii value of '0'
.FILL 49
.FILL 50
.FILL 51
.FILL 52
.FILL 53
.FILL 54
.FILL 55
.FILL 56
.FILL 57
.FILL 65 ;A
.FILL 66
.FILL 67
.FILL 68
.FILL 69
.FILL 70
PRINTF_MINUS .FILL 45
PRINTF_BUF .BLKW 18
lc3_printf
ADD R6, R6, #-2
STR R7, R6, #0 ;return address
ADD R6, R6, #-1
STR R5, R6, #0
ADD R5, R6, #-1
ADD R6, R6, #-1
STR R4, R6, #0
ADD R5, R5, #4 ;cheating with the bp (no longer bp)
LDR R4, R5, #0 ;got addr of format string
PRINTF_LOOP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
LDR R0, R4, #0
ADD R0, R0, #0 ;End of string? (0x0000)
BRz PRINTF_DONE
ADD R2, R0, #0
LD R1, PRINTF_PERCENT
ADD R2, R2, R1
BRnp PRINTF_CHAR
ADD R4, R4, #1
LDR R0, R4, #0
;is it %c?
ADD R2, R0, #0
LD R3, PRINTF_C
ADD R2, R2, R3
BRnp PRINTF_CHECKSTR
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;%c
ADD R5, R5, #1
LDR R0, R5, #0
PRINTF_CHAR
OUT
ADD R4, R4, #1
BRnzp PRINTF_LOOP
PRINTF_CHECKSTR
;is it %s?
ADD R2, R0, #0
LD R7, PRINTF_S
ADD R2, R2, R7
BRnp PRINTF_CHECKDEC
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;%s
ADD R5, R5, #1
LDR R0, R5, #0
PUTS
ADD R4, R4, #1
BRnzp PRINTF_LOOP
PRINTF_CHECKDEC
;is it %d?
ADD R2, R0, #0
LD R7, PRINTF_D
ADD R2, R2, R7
;BRnp PRINTF_ERROR
BRnp PRINTF_CHECKHEX
AND R2, R2, #0
ADD R2, R2, #-10 ;going to divide by 10 by using sub loop
BRnzp PRINTF_NUM
PRINTF_CHECKHEX
ADD R2, R0, #0
LD R7, PRINTF_X
ADD R2, R2, R7
BRnp PRINTF_CHECKOCT
AND R2, R2, #0
ADD R2, R2, #-16 ;going to divide by 10 by using sub loop
BRnzp PRINTF_NUM
PRINTF_CHECKOCT
ADD R2, R0, #0
LD R7, PRINTF_O
ADD R2, R2, R7
BRnp PRINTF_CHECKBIN
AND R2, R2, #0
ADD R2, R2, #-8 ;going to divide by 10 by using sub loop
BRnzp PRINTF_NUM
PRINTF_CHECKBIN
ADD R2, R0, #0
LD R7, PRINTF_B
ADD R2, R2, R7
BRnp PRINTF_ERROR
AND R2, R2, #0
ADD R2, R2, #-2 ;going to divide by 10 by using sub loop
;BRnzp PRINTF_NUM
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;%d
PRINTF_NUM
LEA R7, PRINTF_BUF
ADD R7, R7, #15
ADD R7, R7, #1
;AND R2, R2, #0
;ADD R2, R2, #-10 ;going to divide by 10 by using sub loop
ADD R5, R5, #1 ;acquire the binary number
LDR R0, R5, #0
ADD R0, R0, #0
BRzp PRINTF_DECPOS
NOT R0, R0 ;make num positive for sub loop
ADD R0, R0, #1
PRINTF_DECPOS
AND R3, R3, #0
ADD R3, R3, #-1
PRINTF_DIVLOOP
ADD R3, R3, #1 ;num/10
ADD R0, R0, R2 ;R0 = num % 10 - 10
BRzp PRINTF_DIVLOOP
ADD R3, R3, #0
BRz PRINTF_LASTDIGIT
;LD R1, PRINTF_ASCII
;ADD R1, R1, R0
;NOT R2, R2
;ADD R1, R1, R2
;ADD R1, R1, #1
;NOT R2, R2
;;;;;ADD R1, R1, #10
;STR R1, R7, #0
;ADD R7, R7, #-1 ;stored ascii value of one digit
LEA R1, PRINTF_ASCII
ADD R1, R1, R0
NOT R2, R2
ADD R1, R1, R2
ADD R1, R1, #1
NOT R2, R2
LDR R1, R1, #0
STR R1, R7, #0
ADD R7, R7, #-1 ;stored ascii value of one digit
ADD R0, R3, #0 ;num/10
BRnzp PRINTF_DECPOS
PRINTF_LASTDIGIT
;LD R1, PRINTF_ASCII
;ADD R1, R1, R0
;ADD R1, R1, #10
;STR R1, R7, #0
LEA R1, PRINTF_ASCII
ADD R1, R1, R0
NOT R2, R2
ADD R1, R1, R2
ADD R1, R1, #1
NOT R2, R2
LDR R1, R1, #0
STR R1, R7, #0 ;stored ascii value of highest order digit
LDR R0, R5, #0
ADD R0, R0, #0
BRzp PRINTF_DECSTRING
LD R0, PRINTF_MINUS ;num was negative
ADD R7, R7, #-1
STR R0, R7, #0 ;stored ascii value negative sign
PRINTF_DECSTRING ;print the calculated string
ADD R0, R7, #0
PUTS
ADD R4, R4, #1
BRnzp PRINTF_LOOP
PRINTF_ERROR
PRINTF_DONE
LDR R4, R6, #0 ;restore R4
ADD R6, R6, #1
LDR R5, R6, #0 ;restore bp
ADD R6, R6, #1
LDR R7, R6, #0 ;restore ret addr
ADD R6, R6, #1
RET
GLOBAL_DATA_START
L1_Optimize .FILL lc3_L1_Optimize
scanf .FILL lc3_scanf
printf .FILL lc3_printf
L4_Optimize .FILL #0
L3_Optimize .FILL #29
L2_Optimize .STRINGZ "The answer is %d\n"
.END
%reset