CS111 Week 2 Lecture (4/9/13)
by Jacob Sharf, Calvin Cam, and Ian Chen
Case 1- Say that:
Case 2- Say that:
Say that:
In Case 2, we had to make assumptions though. Q: What are these assumptions? - Cost to find module is nothing - Bugs are isolated and not spread throughout the code
"Nice" pieces (simpler than original)
There are some problems with the word-count program from the previous lecture. + Had two copies of read_sector function - Bootloader in MBR - word-count itself
Q: How to fix this?
Solution 1: Put commonly used functions in BIOS (read_sector)
Solution 2: Put it into MBR
Solution 3: Create a library in RAM
CONCLUSION: There are many solutions with different pros, but with unfavorable flaws
TO BE CONTINUED...
wc v. crypto analysis - uses a lot of CPU
I/O -0- -1- -2-
CPU -0- -1- -2-
t ->
I/O -0- -1- -2- -3-
CPI -0- -1- -2-
t ->
Q: Can we use triple buffer? 100 buffering?
A: No, restricted by I/O (bottleneck)
trading complexity for performance
read_sector |------------| <--- internally, it buffers or reads ahead (cache)
void read_sector (int s, int ptr_t a) // s is sector number, a is address
| generalize read_sector
v
int read (int s, intptr_t buf, int bufsize)
| improvements:
| change int return to size_t turn (generalization for computer type)
| change int sector type to off_t sector type (64 bit)
| change intptr_t to void* (generic c pointer)
| change int to size_t
v
size_t read(off_t offset, void* buf, size_t bufsize)
| potential problem: assumes random access device for offset
v
size_t read(void* buf, size_t bufsize) // more general and works w/ any device
+
off_t seek(off_t offset) // for random access devices only
| Add error checking
v
size_t lread(int fd, void* buff, size_t bufsize) // -1 => error, error has details
+
off_t lseek(int fd, off_t offset, int flag) // 0 => SEEK_SET, 1 => SEEK_CUR, 2 => SEEK_END
Mechanism
Method 0
Method 1
_
| | <- program test (read only)
_
| | <- I/O buffers
_
| | <- heap
_
|X| <- FORBIDDEN AREA
_
| | <- Stack
_
| | <- library O.S. kernal (read only)
In C
int fact(int n)
{
if(n)
return n*fact(n-1);
else
return 1;
}
Sidenote: gcc will actually optimize this into the iterative version if you specify -O2. For the recursive version, specify the -O0 command, asking it not to perform any optimizations
In Assembly
fact:
pushl %ebp
movl $1, %eax ;// caller beware! callee can modify %eax
movl %esp, %ebp ;// we'll preserve %ebp, (the frame pointer)
subl $8, %esp
movl %ebx, -4(%ebp) ;// e means extended (more below)
movl 8(%ebp), %ebx
tstl %ebx, %ebx
jne .L5
.L1:
movl -4(%ebp), %ebx
movl %ebp, %esp
popl %ebp
ret ;// answer in %eax
.L5:
leal -1(%ebx), %eax ;// ax = bx-1
movl %eax, (%esp)
call fact
imull %ebx, %eax
jmp .L1
Originally, the x86 architecture used 16-bit registers, which did not have the e in the beginning of their name (ax, bp, sp, etc). As computer architectures moved to 32-bit registers, intel decided to extend their registers to 32-bits. To maintain compatibility, you can refer to the lower 16 bits of the register via >their older names, or to all 32 extended bits by appending an e. In the example above, callee can modify %eax. Caller cannot depend on %eax being preserved across a function call
This sort of caller-callee contract is called the calling convention
Q: What can go wrong with function call modularity? A: Robustness - Caller could mess up (e.g. it would forget to push in; jmp fact instead of call fact) + when we return, we'll execute random instructions - Callee can mess up (e.g. callee can set registers it's not supposed to; callee can return to wherever it wants to; callee can loop) - all these bugs happen -> we want to allow O.S. to run regardless of buggy modules
Voluntary conventions which rely on the participation of the caller and
callee
Functional calls give you SOFT MODULARITY - We want HARD MODULARITY
Modularity which does not rely on the participation of the caller/callee.
Works even with buggy modules.
Two Common ways:
1. Client-Server: Code is put on a centralized server. Since all communication is done over a network connection, the client connecting cannot write on server memory, and it can’t execute arbitrary instructions over a truly secure network.
- Pro: Very robust
- Con: Very Expensive