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

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
    • Advanced functionality:
      • 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;
}

// Newer style:
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>:
  400200:	2f                   	(bad)  
  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
  40021e:	00 00                	add    %al,(%rax)
  400220:	10 00                	adc    %al,(%rax)
  400222:	00 00                	add    %al,(%rax)
  400224:	01 00                	add    %eax,(%rax)
  400226:	00 00                	add    %al,(%rax)
  400228:	47                   	rex.RXB
  400229:	4e 55                	rex.WRX push %rbp
  40022b:	00 00                	add    %al,(%rax)
  40022d:	00 00                	add    %al,(%rax)
  40022f:	00 02                	add    %al,(%rdx)
  400231:	00 00                	add    %al,(%rax)
  400233:	00 06                	add    %al,(%rsi)
  400235:	00 00                	add    %al,(%rax)
  400237:	00 12                	add    %dl,(%rdx)
  400239:	00 00                	add    %al,(%rax)
	...

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
  400242:	00 00                	add    %al,(%rax)
  400244:	03 00                	add    (%rax),%eax
  400246:	00 00                	add    %al,(%rax)
  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)
  40030d:	61                   	(bad)  
  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)
  400342:	00 00                	add    %al,(%rax)
  400344:	00 00                	add    %al,(%rax)
	...

Disassembly of section .rela.dyn:

0000000000400348 <.rela.dyn>:
  400348:	48 08 60 00          	rex.W or %spl,0x0(%rax)
  40034c:	00 00                	add    %al,(%rax)
  40034e:	00 00                	add    %al,(%rax)
  400350:	06                   	(bad)  
  400351:	00 00                	add    %al,(%rax)
  400353:	00 01                	add    %al,(%rcx)
	...

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>:
  4005ec:	01 1b                	add    %ebx,(%rbx)
  4005ee:	03 3b                	add    (%rbx),%edi
  4005f0:	20 00                	and    %al,(%rax)
  4005f2:	00 00                	add    %al,(%rax)
  4005f4:	03 00                	add    (%rax),%eax
  4005f6:	00 00                	add    %al,(%rax)
  4005f8:	d8 fe                	fdivr  %st(6),%st
  4005fa:	ff                   	(bad)  
  4005fb:	ff                   	(bad)  
  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
  400612:	00 00                	add    %al,(%rax)
  400614:	00 00                	add    %al,(%rax)
  400616:	00 00                	add    %al,(%rax)
  400618:	01 7a 52             	add    %edi,0x52(%rdx)
  40061b:	00 01                	add    %al,(%rcx)
  40061d:	78 10                	js     40062f <__dso_handle+0x5f>
  40061f:	01 1b                	add    %ebx,(%rbx)
  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)
  400646:	00 00                	add    %al,(%rax)
  400648:	14 00                	adc    $0x0,%al
  40064a:	00 00                	add    %al,(%rax)
  40064c:	3c 00                	cmp    $0x0,%al
  40064e:	00 00                	add    %al,(%rax)
  400650:	90                   	nop
  400651:	fe                   	(bad)  
  400652:	ff                   	(bad)  
  400653:	ff 02                	incl   (%rdx)
	...
  40065d:	00 00                	add    %al,(%rax)
  40065f:	00 24 00             	add    %ah,(%rax,%rax,1)
  400662:	00 00                	add    %al,(%rax)
  400664:	54                   	push   %rsp
  400665:	00 00                	add    %al,(%rax)
  400667:	00 88 fe ff ff 89    	add    %cl,-0x76000002(%rax)
  40066d:	00 00                	add    %al,(%rax)
  40066f:	00 00                	add    %al,(%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
  6006ca:	00 00                	add    %al,(%rax)
  6006cc:	00 00                	add    %al,(%rax)
  6006ce:	00 00                	add    %al,(%rax)
  6006d0:	90                   	nop
  6006d1:	03 40 00             	add    0x0(%rax),%eax
  6006d4:	00 00                	add    %al,(%rax)
  6006d6:	00 00                	add    %al,(%rax)
  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
	...
  600865:	00 00                	add    %al,(%rax)
  600867:	00 be 03 40 00 00    	add    %bh,0x4003(%rsi)
  60086d:	00 00                	add    %al,(%rax)
  60086f:	00 ce                	add    %cl,%dh
  600871:	03 40 00             	add    0x0(%rax),%eax
  600874:	00 00                	add    %al,(%rax)
	...

Disassembly of section .data:

0000000000600878 <__data_start>:
  600878:	00 00                	add    %al,(%rax)
	...

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
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
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() {
    printf("The answer is %d\n", 88/3);
    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
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
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