## Jupyter at Bryn Mawr College

Public notebooks: /services/public/dblank / CS240 Computer Organization / 2015-Fall / Notes

# 1. Randomness¶

## 1.1 How can the LC-3 create random numbers?¶

It can't. It is a deterministic computer with no means of reaching outside of itself.

## 1.2 Pseudo-Random Number Generator Algorithm¶

In [146]:
%%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)

70
490
3430
24010
4235
29645
10913
10857
10465
7721
21280
17892
26943
24766
9527
1155
8085
23828
2961
20727


The LC-3 Assembly code:

Produces exactly the same numbers, in the same sequence.

# 2. Languages¶

What have ween seen so far:

1. Machine code - zeros and ones
2. Assembly Language
• two-pass system: labels
• mnemonics for instructions, registers, etc.
• directives (.FILL, .STRINGZ, .STRINGC)
• decimal, hex representations
3. C Language
• macros, defines, conditional compiling
• functions
• structs
• memory functions
• libraries
• Some optimizations
4. C++ Language
• garbage collection
• OOP - Object-Oriented Programming
• inheritance
• public/private
5. Advanced Languages (Python, Java, Scheme, JavaScript, etc.)
• Many have their own virtual machine and assembly language
• Many have a Just-In-Time Compiler (JIT)
• Adapt as they run (uses statistics of specifics)
• Largely, Machine Learning/Artificial Intelligence has not been used yet
• Type Inference
• Backtracking
• Pure Functional

# 3. The C Programming Language¶

## 3.1 Overview¶

Generally described as:

• Statically Typed - types checked at compile type
• Weakly Typed - programmer can manipulate types (convert one to another, casting)
• "Super assembly"
• Can write code that translates almost directly into assembly language instructions
• "Syntactic sugar" - easy to write/read; fast
• Generates necessary instructions for handling functions, and structs
• There are C compilers for "all" hardware

## 3.2 Hello, world!¶

#include <stdio.h>

int main() {
printf("Hello, world!");
return 0;
}

• All variables and functions must be defined before use
• All variables and functions have a type
• int, double, float
• uint - unsigned int
• char is really uint
• strings are arrays of char
• Arrays - contiguous blocks of memory
• the type determines the offset between elements
• they don't know how long they are

# 4. C with Linux¶

1. Create a text file with C source code in it
• must have a main()
• type can be int, or void
• include additional libraries with #include
2. Compile it
3. Run it

## 4.1 Create a C source code file¶

In [149]:
%%file Test1.c

#include <stdio.h>
int main() {
printf("Testing 1, 2, 3...\n");
return 0;
}

Created file '/home/dblank/public_html/CS240 Computer Organization/2015-Fall/Notes/Test1.c'.


## 4.2 Compile it¶

Using the GNU C Compiler:

In [150]:
! gcc -o Test1 Test1.c


## 4.3 Execute it¶

The current directory (called ".") isn't in your search PATH, so we have to give the path to it.

In [151]:
! ./Test1

Testing 1, 2, 3...



# 5. C Details¶

NOTES:

• If you want to get input from the user using gcc, you'll need to run in a terminal

## 5.1 Interface with Operating System¶

• argc - count
• argv - string parameters
• return value (must be int, if one)
• called "exit codes"; each OS has their own
• Linux/bash:
• OK 0 / successful termination /
• BASE 64 / base value for error messages /
• USAGE 64 / command line usage error /
• DATAERR 65 / data format error /
• ...
• Can print to terminal
#include <stdio.h>

int main(int argc, char **argv) {
printf("Hello World");
return 0;
}


## 5.2 Variables¶

// Old style:
void main() {
int x;     // define and use variables
float f;

x = 1;
f = 3.2;
}

void main() {
int x = 1;     // define and use variables
float f = 3.2;
}


## 5.3 Pointers¶

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;

In [268]:
%%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);
}

Created file '/home/dblank/public_html/CS240 Computer Organization/2015-Fall/Notes/Pointers.c'.

In [269]:
!gcc -o Pointers Pointers.c

In [270]:
!./Pointers

x is: 7
px is: 7



## 5.4 Arrays¶

int array[] = {1, 2, 3};
char *string = "This is a string";
char *sarray[] = {"Hello", "world"};

In [257]:
%%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]);
}

Created file '/home/dblank/public_html/CS240 Computer Organization/2015-Fall/Notes/Arrays.c'.

In [258]:
!gcc -o Arrays Arrays.c

In [259]:
! ./Arrays

This is a string
Hello


## Disassembly of GCC¶

In [273]:
! objdump -D Test1

Test1:     file format elf64-x86-64

Disassembly of section .interp:

0000000000400200 <.interp>:
400201:	6c                   	insb   (%dx),%es:(%rdi)
400202:	69 62 36 34 2f 6c 64 	imul   $0x646c2f34,0x36(%rdx),%esp 400209: 2d 6c 69 6e 75 sub$0x756e696c,%eax
40020e:	78 2d                	js     40023d <_init-0x153>
400210:	78 38                	js     40024a <_init-0x146>
400212:	36                   	ss
400213:	2d 36 34 2e 73       	sub    $0x732e3436,%eax 400218: 6f outsl %ds:(%rsi),(%dx) 400219: 2e 32 00 xor %cs:(%rax),%al Disassembly of section .note.ABI-tag: 000000000040021c <.note.ABI-tag>: 40021c: 04 00 add$0x0,%al
400228:	47                   	rex.RXB
400229:	4e 55                	rex.WRX push %rbp
...

Disassembly of section .note.gnu.build-id:

000000000040023c <.note.gnu.build-id>:
40023c:	04 00                	add    $0x0,%al 40023e: 00 00 add %al,(%rax) 400240: 14 00 adc$0x0,%al
400248:	47                   	rex.RXB
400249:	4e 55                	rex.WRX push %rbp
40024b:	00 be 88 16 16 c8    	add    %bh,-0x37e9e978(%rsi)
400251:	bd 84 f7 ca 9e       	mov    $0x9ecaf784,%ebp 400256: 5c pop %rsp 400257: 77 1f ja 400278 <_init-0x118> 400259: c0 3a 2f sarb$0x2f,(%rdx)
40025c:	a3                   	.byte 0xa3
40025d:	b6 ad                	mov    $0xad,%dh 40025f: 8c .byte 0x8c Disassembly of section .gnu.hash: 0000000000400260 <.gnu.hash>: 400260: 01 00 add %eax,(%rax) 400262: 00 00 add %al,(%rax) 400264: 01 00 add %eax,(%rax) 400266: 00 00 add %al,(%rax) 400268: 01 00 add %eax,(%rax) ... Disassembly of section .dynsym: 0000000000400280 <.dynsym>: ... 400298: 01 00 add %eax,(%rax) 40029a: 00 00 add %al,(%rax) 40029c: 20 00 and %al,(%rax) ... 4002ae: 00 00 add %al,(%rax) 4002b0: 1a 00 sbb (%rax),%al 4002b2: 00 00 add %al,(%rax) 4002b4: 12 00 adc (%rax),%al ... 4002c6: 00 00 add %al,(%rax) 4002c8: 1f (bad) 4002c9: 00 00 add %al,(%rax) 4002cb: 00 12 add %dl,(%rdx) ... Disassembly of section .dynstr: 00000000004002e0 <.dynstr>: 4002e0: 00 5f 5f add %bl,0x5f(%rdi) 4002e3: 67 6d insl (%dx),%es:(%edi) 4002e5: 6f outsl %ds:(%rsi),(%dx) 4002e6: 6e outsb %ds:(%rsi),(%dx) 4002e7: 5f pop %rdi 4002e8: 73 74 jae 40035e <_init-0x32> 4002ea: 61 (bad) 4002eb: 72 74 jb 400361 <_init-0x2f> 4002ed: 5f pop %rdi 4002ee: 5f pop %rdi 4002ef: 00 6c 69 62 add %ch,0x62(%rcx,%rbp,2) 4002f3: 63 2e movslq (%rsi),%ebp 4002f5: 73 6f jae 400366 <_init-0x2a> 4002f7: 2e 36 00 70 75 cs add %dh,%cs:%ss:0x75(%rax) 4002fc: 74 73 je 400371 <_init-0x1f> 4002fe: 00 5f 5f add %bl,0x5f(%rdi) 400301: 6c insb (%dx),%es:(%rdi) 400302: 69 62 63 5f 73 74 61 imul$0x6174735f,0x63(%rdx),%esp
400309:	72 74                	jb     40037f <_init-0x11>
40030b:	5f                   	pop    %rdi
40030c:	6d                   	insl   (%dx),%es:(%rdi)
40030e:	69 6e 00 47 4c 49 42 	imul   $0x42494c47,0x0(%rsi),%ebp 400315: 43 5f rex.XB pop %r15 400317: 32 2e xor (%rsi),%ch 400319: 32 2e xor (%rsi),%ch 40031b: 35 .byte 0x35 ... Disassembly of section .gnu.version: 000000000040031e <.gnu.version>: 40031e: 00 00 add %al,(%rax) 400320: 00 00 add %al,(%rax) 400322: 02 00 add (%rax),%al 400324: 02 00 add (%rax),%al Disassembly of section .gnu.version_r: 0000000000400328 <.gnu.version_r>: 400328: 01 00 add %eax,(%rax) 40032a: 01 00 add %eax,(%rax) 40032c: 10 00 adc %al,(%rax) 40032e: 00 00 add %al,(%rax) 400330: 10 00 adc %al,(%rax) 400332: 00 00 add %al,(%rax) 400334: 00 00 add %al,(%rax) 400336: 00 00 add %al,(%rax) 400338: 75 1a jne 400354 <_init-0x3c> 40033a: 69 09 00 00 02 00 imul$0x20000,(%rcx),%ecx
400340:	31 00                	xor    %eax,(%rax)
...

Disassembly of section .rela.dyn:

0000000000400348 <.rela.dyn>:
400348:	48 08 60 00          	rex.W or %spl,0x0(%rax)
...

Disassembly of section .rela.plt:

0000000000400360 <.rela.plt>:
400360:	68 08 60 00 00       	pushq  $0x6008 400365: 00 00 add %al,(%rax) 400367: 00 07 add %al,(%rdi) 400369: 00 00 add %al,(%rax) 40036b: 00 02 add %al,(%rdx) ... 400375: 00 00 add %al,(%rax) 400377: 00 70 08 add %dh,0x8(%rax) 40037a: 60 (bad) 40037b: 00 00 add %al,(%rax) 40037d: 00 00 add %al,(%rax) 40037f: 00 07 add %al,(%rdi) 400381: 00 00 add %al,(%rax) 400383: 00 03 add %al,(%rbx) ... Disassembly of section .init: 0000000000400390 <_init>: 400390: 48 83 ec 08 sub$0x8,%rsp
400394:	e8 73 00 00 00       	callq  40040c <call_gmon_start>
400399:	e8 02 01 00 00       	callq  4004a0 <frame_dummy>
40039e:	e8 dd 01 00 00       	callq  400580 <__do_global_ctors_aux>
4003a3:	48 83 c4 08          	add    $0x8,%rsp 4003a7: c3 retq Disassembly of section .plt: 00000000004003a8 <puts@plt-0x10>: 4003a8: ff 35 aa 04 20 00 pushq 0x2004aa(%rip) # 600858 <_GLOBAL_OFFSET_TABLE_+0x8> 4003ae: ff 25 ac 04 20 00 jmpq *0x2004ac(%rip) # 600860 <_GLOBAL_OFFSET_TABLE_+0x10> 4003b4: 0f 1f 40 00 nopl 0x0(%rax) 00000000004003b8 <puts@plt>: 4003b8: ff 25 aa 04 20 00 jmpq *0x2004aa(%rip) # 600868 <_GLOBAL_OFFSET_TABLE_+0x18> 4003be: 68 00 00 00 00 pushq$0x0
4003c3:	e9 e0 ff ff ff       	jmpq   4003a8 <_init+0x18>

00000000004003c8 <__libc_start_main@plt>:
4003c8:	ff 25 a2 04 20 00    	jmpq   *0x2004a2(%rip)        # 600870 <_GLOBAL_OFFSET_TABLE_+0x20>
4003ce:	68 01 00 00 00       	pushq  $0x1 4003d3: e9 d0 ff ff ff jmpq 4003a8 <_init+0x18> Disassembly of section .text: 00000000004003e0 <_start>: 4003e0: 31 ed xor %ebp,%ebp 4003e2: 49 89 d1 mov %rdx,%r9 4003e5: 5e pop %rsi 4003e6: 48 89 e2 mov %rsp,%rdx 4003e9: 48 83 e4 f0 and$0xfffffffffffffff0,%rsp
4003ed:	50                   	push   %rax
4003ee:	54                   	push   %rsp
4003ef:	49 c7 c0 e0 04 40 00 	mov    $0x4004e0,%r8 4003f6: 48 c7 c1 f0 04 40 00 mov$0x4004f0,%rcx
4003fd:	48 c7 c7 c4 04 40 00 	mov    $0x4004c4,%rdi 400404: e8 bf ff ff ff callq 4003c8 <__libc_start_main@plt> 400409: f4 hlt 40040a: 90 nop 40040b: 90 nop 000000000040040c <call_gmon_start>: 40040c: 48 83 ec 08 sub$0x8,%rsp
400410:	48 8b 05 31 04 20 00 	mov    0x200431(%rip),%rax        # 600848 <_DYNAMIC+0x190>
400417:	48 85 c0             	test   %rax,%rax
40041a:	74 02                	je     40041e <call_gmon_start+0x12>
40041c:	ff d0                	callq  *%rax
40041e:	48 83 c4 08          	add    $0x8,%rsp 400422: c3 retq 400423: 90 nop 400424: 90 nop 400425: 90 nop 400426: 90 nop 400427: 90 nop 400428: 90 nop 400429: 90 nop 40042a: 90 nop 40042b: 90 nop 40042c: 90 nop 40042d: 90 nop 40042e: 90 nop 40042f: 90 nop 0000000000400430 <__do_global_dtors_aux>: 400430: 55 push %rbp 400431: 48 89 e5 mov %rsp,%rbp 400434: 53 push %rbx 400435: 48 83 ec 08 sub$0x8,%rsp
400439:	80 3d 40 04 20 00 00 	cmpb   $0x0,0x200440(%rip) # 600880 <completed.6347> 400440: 75 4b jne 40048d <__do_global_dtors_aux+0x5d> 400442: bb a8 06 60 00 mov$0x6006a8,%ebx
400447:	48 8b 05 3a 04 20 00 	mov    0x20043a(%rip),%rax        # 600888 <dtor_idx.6349>
40044e:	48 81 eb a0 06 60 00 	sub    $0x6006a0,%rbx 400455: 48 c1 fb 03 sar$0x3,%rbx
400459:	48 83 eb 01          	sub    $0x1,%rbx 40045d: 48 39 d8 cmp %rbx,%rax 400460: 73 24 jae 400486 <__do_global_dtors_aux+0x56> 400462: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1) 400468: 48 83 c0 01 add$0x1,%rax
40046c:	48 89 05 15 04 20 00 	mov    %rax,0x200415(%rip)        # 600888 <dtor_idx.6349>
400473:	ff 14 c5 a0 06 60 00 	callq  *0x6006a0(,%rax,8)
40047a:	48 8b 05 07 04 20 00 	mov    0x200407(%rip),%rax        # 600888 <dtor_idx.6349>
400481:	48 39 d8             	cmp    %rbx,%rax
400484:	72 e2                	jb     400468 <__do_global_dtors_aux+0x38>
400486:	c6 05 f3 03 20 00 01 	movb   $0x1,0x2003f3(%rip) # 600880 <completed.6347> 40048d: 48 83 c4 08 add$0x8,%rsp
400491:	5b                   	pop    %rbx
400492:	c9                   	leaveq
400493:	c3                   	retq
400494:	66 66 66 2e 0f 1f 84 	data32 data32 nopw %cs:0x0(%rax,%rax,1)
40049b:	00 00 00 00 00

00000000004004a0 <frame_dummy>:
4004a0:	48 83 3d 08 02 20 00 	cmpq   $0x0,0x200208(%rip) # 6006b0 <__JCR_END__> 4004a7: 00 4004a8: 55 push %rbp 4004a9: 48 89 e5 mov %rsp,%rbp 4004ac: 74 12 je 4004c0 <frame_dummy+0x20> 4004ae: b8 00 00 00 00 mov$0x0,%eax
4004b3:	48 85 c0             	test   %rax,%rax
4004b6:	74 08                	je     4004c0 <frame_dummy+0x20>
4004b8:	bf b0 06 60 00       	mov    $0x6006b0,%edi 4004bd: c9 leaveq 4004be: ff e0 jmpq *%rax 4004c0: c9 leaveq 4004c1: c3 retq 4004c2: 90 nop 4004c3: 90 nop 00000000004004c4 <main>: 4004c4: 55 push %rbp 4004c5: 48 89 e5 mov %rsp,%rbp 4004c8: bf d8 05 40 00 mov$0x4005d8,%edi
4004cd:	e8 e6 fe ff ff       	callq  4003b8 <puts@plt>
4004d2:	b8 00 00 00 00       	mov    $0x0,%eax 4004d7: c9 leaveq 4004d8: c3 retq 4004d9: 90 nop 4004da: 90 nop 4004db: 90 nop 4004dc: 90 nop 4004dd: 90 nop 4004de: 90 nop 4004df: 90 nop 00000000004004e0 <__libc_csu_fini>: 4004e0: f3 c3 repz retq 4004e2: 66 66 66 66 66 2e 0f data32 data32 data32 data32 nopw %cs:0x0(%rax,%rax,1) 4004e9: 1f 84 00 00 00 00 00 00000000004004f0 <__libc_csu_init>: 4004f0: 48 89 6c 24 d8 mov %rbp,-0x28(%rsp) 4004f5: 4c 89 64 24 e0 mov %r12,-0x20(%rsp) 4004fa: 48 8d 2d 8b 01 20 00 lea 0x20018b(%rip),%rbp # 60068c <__init_array_end> 400501: 4c 8d 25 84 01 20 00 lea 0x200184(%rip),%r12 # 60068c <__init_array_end> 400508: 4c 89 6c 24 e8 mov %r13,-0x18(%rsp) 40050d: 4c 89 74 24 f0 mov %r14,-0x10(%rsp) 400512: 4c 89 7c 24 f8 mov %r15,-0x8(%rsp) 400517: 48 89 5c 24 d0 mov %rbx,-0x30(%rsp) 40051c: 48 83 ec 38 sub$0x38,%rsp
400520:	4c 29 e5             	sub    %r12,%rbp
400523:	41 89 fd             	mov    %edi,%r13d
400526:	49 89 f6             	mov    %rsi,%r14
400529:	48 c1 fd 03          	sar    $0x3,%rbp 40052d: 49 89 d7 mov %rdx,%r15 400530: e8 5b fe ff ff callq 400390 <_init> 400535: 48 85 ed test %rbp,%rbp 400538: 74 1c je 400556 <__libc_csu_init+0x66> 40053a: 31 db xor %ebx,%ebx 40053c: 0f 1f 40 00 nopl 0x0(%rax) 400540: 4c 89 fa mov %r15,%rdx 400543: 4c 89 f6 mov %r14,%rsi 400546: 44 89 ef mov %r13d,%edi 400549: 41 ff 14 dc callq *(%r12,%rbx,8) 40054d: 48 83 c3 01 add$0x1,%rbx
400551:	48 39 eb             	cmp    %rbp,%rbx
400554:	72 ea                	jb     400540 <__libc_csu_init+0x50>
400556:	48 8b 5c 24 08       	mov    0x8(%rsp),%rbx
40055b:	48 8b 6c 24 10       	mov    0x10(%rsp),%rbp
400560:	4c 8b 64 24 18       	mov    0x18(%rsp),%r12
400565:	4c 8b 6c 24 20       	mov    0x20(%rsp),%r13
40056a:	4c 8b 74 24 28       	mov    0x28(%rsp),%r14
40056f:	4c 8b 7c 24 30       	mov    0x30(%rsp),%r15
400574:	48 83 c4 38          	add    $0x38,%rsp 400578: c3 retq 400579: 90 nop 40057a: 90 nop 40057b: 90 nop 40057c: 90 nop 40057d: 90 nop 40057e: 90 nop 40057f: 90 nop 0000000000400580 <__do_global_ctors_aux>: 400580: 55 push %rbp 400581: 48 89 e5 mov %rsp,%rbp 400584: 53 push %rbx 400585: 48 83 ec 08 sub$0x8,%rsp
400589:	48 8b 05 00 01 20 00 	mov    0x200100(%rip),%rax        # 600690 <__CTOR_LIST__>
400590:	48 83 f8 ff          	cmp    $0xffffffffffffffff,%rax 400594: 74 19 je 4005af <__do_global_ctors_aux+0x2f> 400596: bb 90 06 60 00 mov$0x600690,%ebx
40059b:	0f 1f 44 00 00       	nopl   0x0(%rax,%rax,1)
4005a0:	48 83 eb 08          	sub    $0x8,%rbx 4005a4: ff d0 callq *%rax 4005a6: 48 8b 03 mov (%rbx),%rax 4005a9: 48 83 f8 ff cmp$0xffffffffffffffff,%rax
4005ad:	75 f1                	jne    4005a0 <__do_global_ctors_aux+0x20>
4005af:	48 83 c4 08          	add    $0x8,%rsp 4005b3: 5b pop %rbx 4005b4: c9 leaveq 4005b5: c3 retq 4005b6: 90 nop 4005b7: 90 nop Disassembly of section .fini: 00000000004005b8 <_fini>: 4005b8: 48 83 ec 08 sub$0x8,%rsp
4005bc:	e8 6f fe ff ff       	callq  400430 <__do_global_dtors_aux>
4005c1:	48 83 c4 08          	add    $0x8,%rsp 4005c5: c3 retq Disassembly of section .rodata: 00000000004005c8 <_IO_stdin_used>: 4005c8: 01 00 add %eax,(%rax) 4005ca: 02 00 add (%rax),%al 4005cc: 00 00 add %al,(%rax) ... 00000000004005d0 <__dso_handle>: ... 4005d8: 54 push %rsp 4005d9: 65 gs 4005da: 73 74 jae 400650 <__dso_handle+0x80> 4005dc: 69 6e 67 20 31 2c 20 imul$0x202c3120,0x67(%rsi),%ebp
4005e3:	32 2c 20             	xor    (%rax,%riz,1),%ch
4005e6:	33 2e                	xor    (%rsi),%ebp
4005e8:	2e                   	cs
4005e9:	2e                   	cs
...

Disassembly of section .eh_frame_hdr:

00000000004005ec <.eh_frame_hdr>:
4005f0:	20 00                	and    %al,(%rax)
4005f8:	d8 fe                	fdivr  %st(6),%st
4005fc:	3c 00                	cmp    $0x0,%al 4005fe: 00 00 add %al,(%rax) 400600: f4 hlt 400601: fe (bad) 400602: ff (bad) 400603: ff 5c 00 00 lcallq *0x0(%rax,%rax,1) 400607: 00 04 ff add %al,(%rdi,%rdi,8) 40060a: ff (bad) 40060b: ff 74 00 00 pushq 0x0(%rax,%rax,1) ... Disassembly of section .eh_frame: 0000000000400610 <__FRAME_END__-0x78>: 400610: 14 00 adc$0x0,%al
400618:	01 7a 52             	add    %edi,0x52(%rdx)
40061d:	78 10                	js     40062f <__dso_handle+0x5f>
400621:	0c 07                	or     $0x7,%al 400623: 08 90 01 00 00 1c or %dl,0x1c000001(%rax) 400629: 00 00 add %al,(%rax) 40062b: 00 1c 00 add %bl,(%rax,%rax,1) 40062e: 00 00 add %al,(%rax) 400630: 94 xchg %eax,%esp 400631: fe (bad) 400632: ff (bad) 400633: ff 15 00 00 00 00 callq *0x0(%rip) # 400639 <__dso_handle+0x69> 400639: 41 0e rex.B (bad) 40063b: 10 86 02 43 0d 06 adc %al,0x60d4302(%rsi) 400641: 50 push %rax 400642: 0c 07 or$0x7,%al
400644:	08 00                	or     %al,(%rax)
400648:	14 00                	adc    $0x0,%al 40064a: 00 00 add %al,(%rax) 40064c: 3c 00 cmp$0x0,%al
400650:	90                   	nop
400653:	ff 02                	incl   (%rdx)
...
40065f:	00 24 00             	add    %ah,(%rax,%rax,1)
400664:	54                   	push   %rsp
400667:	00 88 fe ff ff 89    	add    %cl,-0x76000002(%rax)
400671:	51                   	push   %rcx
400672:	8c 05 86 06 5f 0e    	mov    %es,0xe5f0686(%rip)        # e9f0cfe <_end+0xe3f046e>
400678:	40 83 07 8f          	rex addl $0xffffffffffffff8f,(%rdi) 40067c: 02 8e 03 8d 04 02 add 0x2048d03(%rsi),%cl 400682: 58 pop %rax 400683: 0e (bad) 400684: 08 00 or %al,(%rax) ... 0000000000400688 <__FRAME_END__>: 400688: 00 00 add %al,(%rax) ... Disassembly of section .ctors: 0000000000600690 <__CTOR_LIST__>: 600690: ff (bad) 600691: ff (bad) 600692: ff (bad) 600693: ff (bad) 600694: ff (bad) 600695: ff (bad) 600696: ff (bad) 600697: ff 00 incl (%rax) 0000000000600698 <__CTOR_END__>: ... Disassembly of section .dtors: 00000000006006a0 <__DTOR_LIST__>: 6006a0: ff (bad) 6006a1: ff (bad) 6006a2: ff (bad) 6006a3: ff (bad) 6006a4: ff (bad) 6006a5: ff (bad) 6006a6: ff (bad) 6006a7: ff 00 incl (%rax) 00000000006006a8 <__DTOR_END__>: ... Disassembly of section .jcr: 00000000006006b0 <__JCR_END__>: ... Disassembly of section .dynamic: 00000000006006b8 <_DYNAMIC>: 6006b8: 01 00 add %eax,(%rax) 6006ba: 00 00 add %al,(%rax) 6006bc: 00 00 add %al,(%rax) 6006be: 00 00 add %al,(%rax) 6006c0: 10 00 adc %al,(%rax) 6006c2: 00 00 add %al,(%rax) 6006c4: 00 00 add %al,(%rax) 6006c6: 00 00 add %al,(%rax) 6006c8: 0c 00 or$0x0,%al
6006d0:	90                   	nop
6006d1:	03 40 00             	add    0x0(%rax),%eax
6006d8:	0d 00 00 00 00       	or     $0x0,%eax 6006dd: 00 00 add %al,(%rax) 6006df: 00 b8 05 40 00 00 add %bh,0x4005(%rax) 6006e5: 00 00 add %al,(%rax) 6006e7: 00 f5 add %dh,%ch 6006e9: fe (bad) 6006ea: ff 6f 00 ljmpq *0x0(%rdi) 6006ed: 00 00 add %al,(%rax) 6006ef: 00 60 02 add %ah,0x2(%rax) 6006f2: 40 00 00 add %al,(%rax) 6006f5: 00 00 add %al,(%rax) 6006f7: 00 05 00 00 00 00 add %al,0x0(%rip) # 6006fd <_DYNAMIC+0x45> 6006fd: 00 00 add %al,(%rax) 6006ff: 00 e0 add %ah,%al 600701: 02 40 00 add 0x0(%rax),%al 600704: 00 00 add %al,(%rax) 600706: 00 00 add %al,(%rax) 600708: 06 (bad) 600709: 00 00 add %al,(%rax) 60070b: 00 00 add %al,(%rax) 60070d: 00 00 add %al,(%rax) 60070f: 00 80 02 40 00 00 add %al,0x4002(%rax) 600715: 00 00 add %al,(%rax) 600717: 00 0a add %cl,(%rdx) 600719: 00 00 add %al,(%rax) 60071b: 00 00 add %al,(%rax) 60071d: 00 00 add %al,(%rax) 60071f: 00 3d 00 00 00 00 add %bh,0x0(%rip) # 600725 <_DYNAMIC+0x6d> 600725: 00 00 add %al,(%rax) 600727: 00 0b add %cl,(%rbx) 600729: 00 00 add %al,(%rax) 60072b: 00 00 add %al,(%rax) 60072d: 00 00 add %al,(%rax) 60072f: 00 18 add %bl,(%rax) 600731: 00 00 add %al,(%rax) 600733: 00 00 add %al,(%rax) 600735: 00 00 add %al,(%rax) 600737: 00 15 00 00 00 00 add %dl,0x0(%rip) # 60073d <_DYNAMIC+0x85> ... 600745: 00 00 add %al,(%rax) 600747: 00 03 add %al,(%rbx) 600749: 00 00 add %al,(%rax) 60074b: 00 00 add %al,(%rax) 60074d: 00 00 add %al,(%rax) 60074f: 00 50 08 add %dl,0x8(%rax) 600752: 60 (bad) 600753: 00 00 add %al,(%rax) 600755: 00 00 add %al,(%rax) 600757: 00 02 add %al,(%rdx) 600759: 00 00 add %al,(%rax) 60075b: 00 00 add %al,(%rax) 60075d: 00 00 add %al,(%rax) 60075f: 00 30 add %dh,(%rax) 600761: 00 00 add %al,(%rax) 600763: 00 00 add %al,(%rax) 600765: 00 00 add %al,(%rax) 600767: 00 14 00 add %dl,(%rax,%rax,1) 60076a: 00 00 add %al,(%rax) 60076c: 00 00 add %al,(%rax) 60076e: 00 00 add %al,(%rax) 600770: 07 (bad) 600771: 00 00 add %al,(%rax) 600773: 00 00 add %al,(%rax) 600775: 00 00 add %al,(%rax) 600777: 00 17 add %dl,(%rdi) 600779: 00 00 add %al,(%rax) 60077b: 00 00 add %al,(%rax) 60077d: 00 00 add %al,(%rax) 60077f: 00 60 03 add %ah,0x3(%rax) 600782: 40 00 00 add %al,(%rax) 600785: 00 00 add %al,(%rax) 600787: 00 07 add %al,(%rdi) 600789: 00 00 add %al,(%rax) 60078b: 00 00 add %al,(%rax) 60078d: 00 00 add %al,(%rax) 60078f: 00 48 03 add %cl,0x3(%rax) 600792: 40 00 00 add %al,(%rax) 600795: 00 00 add %al,(%rax) 600797: 00 08 add %cl,(%rax) 600799: 00 00 add %al,(%rax) 60079b: 00 00 add %al,(%rax) 60079d: 00 00 add %al,(%rax) 60079f: 00 18 add %bl,(%rax) 6007a1: 00 00 add %al,(%rax) 6007a3: 00 00 add %al,(%rax) 6007a5: 00 00 add %al,(%rax) 6007a7: 00 09 add %cl,(%rcx) 6007a9: 00 00 add %al,(%rax) 6007ab: 00 00 add %al,(%rax) 6007ad: 00 00 add %al,(%rax) 6007af: 00 18 add %bl,(%rax) 6007b1: 00 00 add %al,(%rax) 6007b3: 00 00 add %al,(%rax) 6007b5: 00 00 add %al,(%rax) 6007b7: 00 fe add %bh,%dh 6007b9: ff (bad) 6007ba: ff 6f 00 ljmpq *0x0(%rdi) 6007bd: 00 00 add %al,(%rax) 6007bf: 00 28 add %ch,(%rax) 6007c1: 03 40 00 add 0x0(%rax),%eax 6007c4: 00 00 add %al,(%rax) 6007c6: 00 00 add %al,(%rax) 6007c8: ff (bad) 6007c9: ff (bad) 6007ca: ff 6f 00 ljmpq *0x0(%rdi) 6007cd: 00 00 add %al,(%rax) 6007cf: 00 01 add %al,(%rcx) 6007d1: 00 00 add %al,(%rax) 6007d3: 00 00 add %al,(%rax) 6007d5: 00 00 add %al,(%rax) 6007d7: 00 f0 add %dh,%al 6007d9: ff (bad) 6007da: ff 6f 00 ljmpq *0x0(%rdi) 6007dd: 00 00 add %al,(%rax) 6007df: 00 1e add %bl,(%rsi) 6007e1: 03 40 00 add 0x0(%rax),%eax ... Disassembly of section .got: 0000000000600848 <.got>: ... Disassembly of section .got.plt: 0000000000600850 <_GLOBAL_OFFSET_TABLE_>: 600850: b8 06 60 00 00 mov$0x6006,%eax
...
600867:	00 be 03 40 00 00    	add    %bh,0x4003(%rsi)
600871:	03 40 00             	add    0x0(%rax),%eax
...

Disassembly of section .data:

0000000000600878 <__data_start>:
...

Disassembly of section .bss:

0000000000600880 <completed.6347>:
...

0000000000600888 <dtor_idx.6349>:
...

Disassembly of section .comment:

0000000000000000 <.comment>:
0:	47                   	rex.RXB
1:	43                   	rex.XB
2:	43 3a 20             	rex.XB cmp (%r8),%spl
5:	28 47 4e             	sub    %al,0x4e(%rdi)
8:	55                   	push   %rbp
9:	29 20                	sub    %esp,(%rax)
b:	34 2e                	xor    $0x2e,%al d: 34 2e xor$0x2e,%al
f:	36 20 32             	and    %dh,%ss:(%rdx)
12:	30 31                	xor    %dh,(%rcx)
14:	32 30                	xor    (%rax),%dh
16:	33 30                	xor    (%rax),%esi
18:	35 20 28 52 65       	xor    $0x65522820,%eax 1d: 64 20 48 61 and %cl,%fs:0x61(%rax) 21: 74 20 je 43 <_init-0x40034d> 23: 34 2e xor$0x2e,%al
25:	34 2e                	xor    $0x2e,%al 27: 36 ss 28: 2d .byte 0x2d 29: 34 29 xor$0x29,%al
...



# 6. C with the LC-3¶

## 6.1 Setup¶

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:

In [11]:
%%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.

In [4]:
%%shell

echo \$PATH

/opt/lcc:/usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/maui/sbin:/usr/local/maui/bin:/opt/pssc/bin:/opt/openmpi/bin:/opt/torque/bin:/opt/torque/sbin:/root/bin:/opt/pssc/bin:/opt/openmpi/bin:/opt/torque/bin:/opt/torque/sbin:/opt/pssc/bin:/opt/openmpi/bin:/opt/torque/bin:/opt/torque/sbin



## 6.2 Creating a C Program¶

#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:

In [1]:
%%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);
}

Created file '/home/dblank/public_html/CS240 Computer Organization/2015-Fall/Notes/Testme.c'.


## 6.3 Compile the C Program¶

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

In [6]:
%%shell

lcc -o Testme.obj Testme.c

cpp: Testme.c:12 No newline at end of file
STARTING PASS 1
0 errors found in first pass.
STARTING PASS 2
0 errors found in second pass.



## 6.4 Examine the Assembly Language¶

When creating a executable, the C Compiler will first create an .asm file from the C source:

In [3]:
%load Testme.asm

In [205]:
.Orig x3000
INIT_CODE
LEA R6, #-1
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
STR R7, R6, #0
STR R5, R6, #0

ldr R7, R7, #0
str R7, R5, #0
ldr R7, R5, #0
STR R0, R6, #0
STR R1, R6, #0
STR R7, R6, #0
AND R1, R1, #0
BRz L6
BRp L5
NOT R7, R7
L5
BRnp L5
L6
LDR R7, R6, #0
BRzp L7
NOT R1, R1
L7
;bef epilogue x=1 y=0 z=7
LDR R1, R6, #0
LDR R0, R6, #0
;aft epilogue x=1 y=0 z=7
ldr R3, R3, #0
str R7, R5, #-1
ldr R7, R5, #-1
STR R7, R6, #0
STR R7, R6, #0
LDR R0, R0, #0
jsrr R0
lc3_L1_Testme
STR R7, R5, #3
LDR R5, R6, #0
LDR R7, R6, #0
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
STR R7, R6, #0

ADD R6, R6, #-1		;save R5 = bp
STR R5, R6, #0

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

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;% 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?
BRnp SCANF_CHECKD

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;%c found
LDR R2, R5, #0		;R2 has addr for char to be read into

GETC
OUT
STR R0, R2, #0

BRnzp SCANF_LOOP

SCANF_CHECKD
;is it %d?
LD R1, SCANF_D
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

BRZP SCANF_CHECKEDLOWER

LDR R0, R4, #0
LD R7, SCANF_MINUS
BRz SCANF_CHECKEDLOWER

LEA R0, SCANF_BUF
NOT R0, 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
BRNZ SCANF_CHECKEDUPPER

LEA R0, SCANF_BUF
NOT R0, 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

NOT R0, R0
BRz SCANF_NUMDONE	  ;buffer is full

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
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

NOT R1, R7
BRz SCANF_CALCDONE
;R2 = 10*R2
AND R1, R1, #0
ADD R1, R1, #9 ;R1 = counter

SCANF_MULLOOP
BRnp SCANF_MULLOOP

BRnzp SCANF_CALC

SCANF_CALCDONE

LD R0, SCANF_MINUS
LD R1, SCANF_BUF
BRnp SCANF_NOTNEG
NOT R2, R2

SCANF_NOTNEG

LDR R0, R5, #0

STR R2, R0, #0	   ;store decimal number into address

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
BRnp SCANF_ERROR

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;%s found
ADD R6, R6, #-1		;saving current ptr into format string
STR R4, R6, #0

LDR R4, R5, #0

SCANSTRLOOP
GETC
OUT
STR R0, R4, #0		;Reading and storing typed char

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

BRnzp SCANF_LOOP

SCANF_MATCHCHAR
GETC
OUT
NOT R0, R0
BRz SCANF_LOOP

SCANF_ERROR
SCANF_DONE

LDR R4, R6, #0		;restore R4

LDR R5, R6, #0		;restore bp

LDR R7, R6, #0		;restore ret addr

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
STR R7, R6, #0		;return address
STR R5, R6, #0

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

LD R1, PRINTF_PERCENT
BRnp PRINTF_CHAR

LDR R0, R4, #0
;is it %c?
LD R3, PRINTF_C
BRnp PRINTF_CHECKSTR
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;%c
LDR R0, R5, #0

PRINTF_CHAR
OUT

BRnzp PRINTF_LOOP

PRINTF_CHECKSTR
;is it %s?
LD R7, PRINTF_S
BRnp PRINTF_CHECKDEC

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;%s

LDR R0, R5, #0
PUTS

BRnzp PRINTF_LOOP

PRINTF_CHECKDEC
;is it %d?
LD R7, PRINTF_D
;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

LD R7, PRINTF_X
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

LD R7, PRINTF_O
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

LD R7, PRINTF_B
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

;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

BRzp PRINTF_DECPOS

NOT R0, R0				;make num positive for sub loop

PRINTF_DECPOS

AND R3, R3, #0

PRINTF_DIVLOOP
ADD R0, R0, R2			;R0 = num % 10 - 10
BRzp PRINTF_DIVLOOP

BRz PRINTF_LASTDIGIT

;LD R1, PRINTF_ASCII
;NOT R2, R2
;NOT R2, R2
;STR R1, R7, #0
;ADD R7, R7, #-1			;stored ascii value of one digit

LEA R1, PRINTF_ASCII
NOT R2, R2
NOT R2, R2
LDR R1, R1, #0
STR R1, R7, #0
ADD R7, R7, #-1			;stored ascii value of one digit

BRnzp PRINTF_DECPOS

PRINTF_LASTDIGIT

;LD R1, PRINTF_ASCII
;STR R1, R7, #0

LEA R1, PRINTF_ASCII
NOT R2, R2
NOT R2, R2
LDR R1, R1, #0
STR R1, R7, #0			;stored ascii value of highest order digit

LDR R0, R5, #0
BRzp PRINTF_DECSTRING

LD R0, PRINTF_MINUS		;num was negative
STR R0, R7, #0			;stored ascii value negative sign

PRINTF_DECSTRING		;print the calculated string
PUTS

BRnzp PRINTF_LOOP

PRINTF_ERROR
PRINTF_DONE

LDR R4, R6, #0		;restore R4

LDR R5, R6, #0		;restore bp

LDR R7, R6, #0		;restore ret addr

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

Warning: Possible overflow of immediate: -16 at line 458


Assembled! Use %dis or %dump to examine.

In [206]:
%exe

Result = 28
============================================================
Computation completed
============================================================
Instructions: 367
Cycles: 2721 (0.001360 milliseconds)

============================================================
Registers:
============================================================
PC: x048E
N: 1 Z: 0 P: 0
R0: x0000 R1: xFFDB R2: xFFE5 R3: x0000
R4: x3181 R5: xEFFF R6: xEFFE R7: x300C

In [232]:
%%file Optimize.c
#include <stdio.h>

int main() {
return 0;
}

Created file '/home/dblank/public_html/CS240 Computer Organization/2015-Fall/Notes/Optimize.c'.

In [233]:
!lcc -o Optimize.obj Optimize.c

cpp: Optimize.c:6 No newline at end of file
STARTING PASS 1
0 errors found in first pass.
STARTING PASS 2
0 errors found in second pass.


In [234]:
%include Optimize.asm

Warning: Possible overflow of immediate: -16 at line 419


Assembled! Use %dis or %dump to examine; use %exe to run.

In [235]:
%exe

The answer is 29
============================================================
Computation completed
============================================================
Instructions: 405
Cycles: 3059 (0.001530 milliseconds)

============================================================
Registers:
============================================================
PC: x048E
N: 1 Z: 0 P: 0
R0: x0000 R1: xFFDB R2: xFFE5 R3: x0000
R4: x315F R5: xEFFF R6: xEFFE R7: x300C

In [ ]:
%load Optimize.asm

In [ ]:
.Orig x3000
INIT_CODE
LEA R6, #-1
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
STR R7, R6, #0
STR R5, R6, #0

ldr R7, R7, #0
STR R7, R6, #0
STR R7, R6, #0
LDR R0, R0, #0
jsrr R0
ldr R7, R7, #0
lc3_L1_Optimize
STR R7, R5, #3
LDR R5, R6, #0
LDR R7, R6, #0
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
STR R7, R6, #0

ADD R6, R6, #-1		;save R5 = bp
STR R5, R6, #0

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

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;% 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?
BRnp SCANF_CHECKD

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;%c found
LDR R2, R5, #0		;R2 has addr for char to be read into

GETC
OUT
STR R0, R2, #0

BRnzp SCANF_LOOP

SCANF_CHECKD
;is it %d?
LD R1, SCANF_D
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

BRZP SCANF_CHECKEDLOWER

LDR R0, R4, #0
LD R7, SCANF_MINUS
BRz SCANF_CHECKEDLOWER

LEA R0, SCANF_BUF
NOT R0, 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
BRNZ SCANF_CHECKEDUPPER

LEA R0, SCANF_BUF
NOT R0, 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

NOT R0, R0
BRz SCANF_NUMDONE	  ;buffer is full

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
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

NOT R1, R7
BRz SCANF_CALCDONE
;R2 = 10*R2
AND R1, R1, #0
ADD R1, R1, #9 ;R1 = counter

SCANF_MULLOOP
BRnp SCANF_MULLOOP

BRnzp SCANF_CALC

SCANF_CALCDONE

LD R0, SCANF_MINUS
LD R1, SCANF_BUF
BRnp SCANF_NOTNEG
NOT R2, R2

SCANF_NOTNEG

LDR R0, R5, #0

STR R2, R0, #0	   ;store decimal number into address

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
BRnp SCANF_ERROR

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;%s found
ADD R6, R6, #-1		;saving current ptr into format string
STR R4, R6, #0

LDR R4, R5, #0

SCANSTRLOOP
GETC
OUT
STR R0, R4, #0		;Reading and storing typed char

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

BRnzp SCANF_LOOP

SCANF_MATCHCHAR
GETC
OUT
NOT R0, R0
BRz SCANF_LOOP

SCANF_ERROR
SCANF_DONE

LDR R4, R6, #0		;restore R4

LDR R5, R6, #0		;restore bp

LDR R7, R6, #0		;restore ret addr

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
STR R7, R6, #0		;return address
STR R5, R6, #0

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

LD R1, PRINTF_PERCENT
BRnp PRINTF_CHAR

LDR R0, R4, #0
;is it %c?
LD R3, PRINTF_C
BRnp PRINTF_CHECKSTR
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;%c
LDR R0, R5, #0

PRINTF_CHAR
OUT

BRnzp PRINTF_LOOP

PRINTF_CHECKSTR
;is it %s?
LD R7, PRINTF_S
BRnp PRINTF_CHECKDEC

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;%s

LDR R0, R5, #0
PUTS

BRnzp PRINTF_LOOP

PRINTF_CHECKDEC
;is it %d?
LD R7, PRINTF_D
;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

LD R7, PRINTF_X
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

LD R7, PRINTF_O
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

LD R7, PRINTF_B
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

;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

BRzp PRINTF_DECPOS

NOT R0, R0				;make num positive for sub loop

PRINTF_DECPOS

AND R3, R3, #0

PRINTF_DIVLOOP
ADD R0, R0, R2			;R0 = num % 10 - 10
BRzp PRINTF_DIVLOOP

BRz PRINTF_LASTDIGIT

;LD R1, PRINTF_ASCII
;NOT R2, R2
;NOT R2, R2
;STR R1, R7, #0
;ADD R7, R7, #-1			;stored ascii value of one digit

LEA R1, PRINTF_ASCII
NOT R2, R2
NOT R2, R2
LDR R1, R1, #0
STR R1, R7, #0
ADD R7, R7, #-1			;stored ascii value of one digit

BRnzp PRINTF_DECPOS

PRINTF_LASTDIGIT

;LD R1, PRINTF_ASCII
;STR R1, R7, #0

LEA R1, PRINTF_ASCII
NOT R2, R2
NOT R2, R2
LDR R1, R1, #0
STR R1, R7, #0			;stored ascii value of highest order digit

LDR R0, R5, #0
BRzp PRINTF_DECSTRING

LD R0, PRINTF_MINUS		;num was negative
STR R0, R7, #0			;stored ascii value negative sign

PRINTF_DECSTRING		;print the calculated string
PUTS

BRnzp PRINTF_LOOP

PRINTF_ERROR
PRINTF_DONE

LDR R4, R6, #0		;restore R4

LDR R5, R6, #0		;restore bp

LDR R7, R6, #0		;restore ret addr

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

In [229]:
%reset

Welcome to the LC-3 simulator.

The contents of the LC-3 tools distribution, including sources, management
tools, and data, are Copyright (c) 2003 Steven S. Lumetta.

The LC-3 tools distribution is free software covered by the GNU General
Public License, and you are welcome to modify it and/or distribute copies
of it under certain conditions.  The file COPYING (distributed with the
tools) specifies those conditions.  There is absolutely no warranty for
the LC-3 tools distribution, as described in the file NO_WARRANTY (also
distributed with the tools).

Have fun.

============================================================
Registers:
============================================================
PC: x3000
N: 0 Z: 1 P: 0
R0: x0000 R1: x0000 R2: x0000 R3: x0000
R4: x0000 R5: x0000 R6: x0000 R7: x0000