C代写:CS240 Introduction to Points

代写C语言中的指针相关作业,涉及到指针和地址使用的方方面面,工作量略大。

Step 0. Introduction

In this lab you will implement memdump to display memory content, introduction to pointers, and implement string functions with pointer.

Type the following commands:

cdcd cs240tar -xvf  /homes/cs240/lab5-ptr-memdump/lab5-src.tar

Step 1. Checking the Endianess

Integers can be represented in memory in two ways: Little-Endian or Big-Endian. In Little-Endian, the least significant byte of the integer is stored the lowest address in memory. In Big-Endian, the least significant byte is stored in the highest address in memory.

cd cs240/lab5-src

Using your favorite editor create a new file called endian.c

Then copy the following code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
int isLittleEndian() {
int a = 0x05;
char * p = (char *) &a;
if (*p==0x05) {
return 1;
}
return 0;
}

int main()
{

if (isLittleEndian()) {
printf("Machine is Little Endian\n");
}
else {
printf("Machine is Big Endian\n");
}
}

This function isLittleEndian() defines a variable a and assigns the number 5 to it. Then it defines a pointer p of type (char *) and assigns the address of a to p. The operand & obtains the address of the variable you place on the right side. A pointer is just an address in memory. In this way, p points to the first byte of the variable a and *p gives the contents of the first byte of a. If the first byte of a, dereferenced as *p, happens to contain the value 5, then it means that the byte in the lowest address of a is the least significant or Little Endian. Otherwise, it means that the byte in the lowest address is the most significant or Big Endian.

Then save the program. Then compile it and run it:

gcc -o endian endian.c./endian

Step 2. Memory Sections

The memory of the program is divided in the following memory sections:

Memory Section NameDescriptionAccess
text (or code segment)This is the area of memory that contains the machine instructions that corresponds to the compiled program. This area is shared by multiple instances of a running program. The text segment also contains constants such as string literals and variables defined using the const keyword.Read, Execute
dataThis area in the memory image of a running program contains storage for initialized global variables, and static variables that are explicitly initialized to a non-zero value. This area is separate for each running instance of a program.Read, Write
bssThis is the memory area that contains storage for uninitialized global variables and static variables that are not explicitly initialized or initialized to zero. It is also separate for each running instance of a program.Read, Write
stackThis region of the memory image of a running program contains storage for the automatic (non-static local) variables of the program. It also stores context-specific information before a function call, e.g. the value of the Instruction Pointer (Program Counter) register before a function call is made. On most architecture the stack grows from higher memory to lower memory addresses. A running instance of a program can have multiple stacks (as in a multithreaded program)Read, Write
heapThis memory region is reserved for dynamically allocating memory for variables, at run time. Dynamic memory allocation is done by using the malloc or calloc functions and new operator.Read, Write
shared librariesThis region contains the executable image of shared libraries being used by the program.Read, Execute

Open a file lab5-src/sections.c and copy the following program:

cd cs240/lab5-srcvim sections.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <stdio.h>
#include <stdlib.h>

int a=5;

int buffer[1000000];

int foo() {
int d;
static int e = 5;

printf("&d=%p &le=%p\n", &d, &e);
}

int main()
{

int b;
static int c;
int * p = (int *) malloc(sizeof(int));
char * str = "Hello World\n";

printf("&a=%p\n", &a);
printf("&b=%p &c=%p\n", &b, &c);
printf("&p=%p p=%p\n", &p, p);
printf("&str=%p str=%p\n", &str, str);
foo();

printf("main=%p &foo=%p\n", main, &foo);
}

Then save the program, compile it and run it.

gcc -o sections sections.c./sections

Create a table like the following one, but with all the variables and sections listed. Make sure that the memory addresses are in ascending order. Print the table and turn it in in next lab.

Address     Variable/Function   Section----------- -----------------   -------0x4005bc    foo                 Text0x4005e1    main                Text

You will turnin lab5-src/memory.txt together with the other files.

Step 3. Memory Dump

Open the file lab5-src/mymemdump.c by

cd cs240/lab5-srcvim mymemdump.c

Read and complete the function mymemdump(char *p, int len) that dumps in hexadecimal byte by byte the memory starting at p len bytes. An example output is given at the end of the program.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void mymemdump(FILE * fd, char * p , int len) {
// Add your code here.
// You may see p as an array.
// p[0] will return the element 0
// p[1] will return the element 1 and so on

fprintf(fd, "0x%016lX: ", (unsigned long) p);
int c = p[0]&0xFF;

// Print first byte as hexadecimal
fprintf(fd, "%02X ", c);

// Print first byte as character
fprintf(fd, "%c", (c>=32&&c<127)?c:'.');
fprintf(fd,"\n");
}

Type make in lab5-src. The file mymemdump.c is linked together with mem.c to form the executable mem. Here is an example of the output. For every line, print the address, each byte in hexadecimal, and then, in the right column, the ascii value. The ascii value will be printed only if the ascii value is visible 32<=c<=127, otherwise, it will print a ..

cs240@data ~/lab5/lab5-src $ ./mem&x=0x7FFF89A62890&y=0x7FFF89A628A80x00007FFF89A62890: 41 33 40 50 09 00 00 00 30 06 9C 50 D7 7F 00 00  [email protected]: 94 28 A6 89 FF 7F 00 00 00 00 00 00 00 00 28 40  (........(@0x00007FFF89A628B0: 48 65 6C 6C 6F 20 77 6F 72 6C 64 0A 00 00 00 00  Hello world.....0x00007FFF89A628C0: FF B2 F0 00 00 00 00 00 00 00 00 00 00 00 00 00  .............head=0x1e830100x0000000001E83010: 30 30 E8 01 00 00 00 00 50 30 E8 01 00 00 00 00  00.....P0.....0x0000000001E83020: 00 00 00 00 00 00 00 00 21 00 00 00 00 00 00 00  ........!.......0x0000000001E83030: 57 65 6C 63 6F 6D 65 20 00 00 00 00 00 00 00 00  Welcome ........0x0000000001E83040: 00 00 00 00 00 00 00 00 21 00 00 00 00 00 00 00  ........!.......0x0000000001E83050: 70 30 E8 01 00 00 00 00 90 30 E8 01 00 00 00 00  p0.....0.....0x0000000001E83060: 00 00 00 00 00 00 00 00 21 00 00 00 00 00 00 00  ........!.......0x0000000001E83070: 74 6F 20 00 00 00 00 00 00 00 00 00 00 00 00 00  to .............0x0000000001E83080: 00 00 00 00 00 00 00 00 21 00 00 00 00 00 00 00  ........!.......cs240@data ~/lab5/lab5-src $

Run your version of memdump that prints the output above. The output may be different than the output above because the addresses will be different. However, the content will be the same. Copy the output into a MSWORD, RTF, or HTML file lab5-src/mem.doc and then with different colors indicate where the following items are located in the output and their value. Also add the following table with the right values. Color each entry in the table with the corresponding color.

Variable            Address of Variable     Value of Variable------------------- ---------------------   -----------------strabyx.ax.ix.bx.pheadhead->strhead->nexthead->next->strhead->next->nexthead->next->next->strhead->next->next->next

Note: Some of the variables are pointers. The Value of pointer is the address it stores.

Hint: The file lab5-src/hintdump.c includes the barebones of the memdump function:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void mymemdump(FILE * fd, char * p , int len) {
int i;
fprintf(fd, "0x%016lX: ", (unsigned long) p);
// Print address of the beginning of p. You need to print
// it every 16 bytes

for (i=0; i < len; i++) {
int c = p[i]&0xFF; // Get value at [p]. The &0xFF is to make
// sure you truncate to 8bits or one byte.

// Print first byte as hexadecimal
fprintf(fd, "%02X ", c);

// Print first byte as character. Only print
// characters >= 32 that are the printable characters.
fprintf(fd, "%c ", (c>=32)?c:'.');

if (i % 16 == 0 ) {
fprintf(fd,"\n");
}
}
}

int main() {
char a[30];
int x;
x = 5;
strcpy(a,"Hello world\n");
mymemdump(stdout,(char*) &x, 64);
}

Step 4. Implement String Functions Using Pointers

In the file mystring.c implement the string functions indicated using pointers. Do not use predefined string functions such as strlen, strcpy etc. You have to write your own. Also, do not use the array operator [ ] and use pointers instead. Run the testall script to verify that your implementation is correct.

mystring.c:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <stdlib.h>
#include "mystring.h"

int mystrlen(char * s) {
return 0;
}

char * mystrcpy(char * dest, char * src) {
return NULL;
}

char * mystrcat(char * dest, char * src) {
return NULL;
}

int mystrcmp(char * s1, char * s2) {
return -1;
}

char * mystrstr(char * hay, char * needle) {
return NULL;
}

char * mystrdup(char * s) {
return NULL;
}

char * mymemcpy(char * dest, char * src, int n)
{

return NULL;
}

Step 5. Implementing Array Functions

Implement the array operations indicated in the file array.c Do not use [ ] and instead use pointers. Run the testall script to verify that they are correct.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <stdio.h>
#include "array.h"

// Return sum of the array
double sumArray(int n, double * array) {
double sum = 0;
double * p = array;
double * pend = p+n;

while (p < pend) {
sum += *p;
p++;
}

return sum;
}

// Return maximum element of array
double maxArray(int n, double * array) {
return 0;
}

// Return minimum element of array
double minArray(int n, double * array) {
return 0;
}

// Find the position int he array of the first element x
// such that min<=x<=max or -1 if no element was found
int findArray(int n, double * array, double min, double max) {
return -1;
}

// Sort array without using [] operator. Use pointers
// Hint: Use a pointer to the current and another to the next element
int sortArray(int n, double * array) {
}

// Print array
void printArray(int n, double * array) {
}

Step 6: File Dump

Using your implementation of MemoryDump in Step 3 write a program:

myfiledump file [maxbytes]

That prints a byte dump similar to MemoryDump but using a file insteqad of memory.

Where file is the name of the file to print. The parameter maxbytes is optional and indicates the number of bytes to print. If maxbytes does not exist, then it will print the entire file.

Write your implementation in the file myfiledump.c.

We give you the file ./myfiledump.org that is our solution to this program so you can compare with.

For example:

cs240@data ~/lab5-ptr-memdump/lab5-src $ ./myfiledump.org mem.c0x0000000000000000: 0A 23 69 6E 63 6C 75 64 65 20 3C 73 74 64 69 6F  .#include <stdio0x0000000000000010: 2E 68 3E 0A 23 69 6E 63 6C 75 64 65 20 3C 73 74  .h>.#include <st0x0000000000000020: 72 69 6E 67 2E 68 3E 0A 23 69 6E 63 6C 75 64 65  ring.h>.#include0x0000000000000030: 20 3C 73 74 64 6C 69 62 2E 68 3E 0A 0A 76 6F 69   <stdlib.h>..voi0x0000000000000040: 64 20 6D 79 6D 65 6D 64 75 6D 70 28 46 49 4C 45  d mymemdump(FILE0x0000000000000050: 20 2A 66 64 2C 20 63 68 61 72 20 2A 20 70 20 2C   *fd, char * p ,0x0000000000000060: 20 69 6E 74 20 6C 65 6E 29 3B 0A 0A 73 74 72 75   int len);..stru

Or

cs240@data ~/lab5-ptr-memdump/lab5-src $ ./myfiledump.org myfiledump.org 1000x0000000000000000: 7F 45 4C 46 02 01 01 00 00 00 00 00 00 00 00 00  .ELF............0x0000000000000010: 02 00 3E 00 01 00 00 00 E0 06 40 00 00 00 00 00  ..>[email protected]: 40 00 00 00 00 00 00 00 88 23 00 00 00 00 00 00  @........#......0x0000000000000030: 00 00 00 00 40 00 38 00 0A 00 40 00 22 00 1F 00  [email protected]...@."...0x0000000000000040: 06 00 00 00 05 00 00 00 40 00 00 00 00 00 00 00  [email protected]: 40 00 40 00 00 00 00 00 40 00 40 00 00 00 00 00  @.@.....@[email protected]: 30 02 00 00                                      0...

Hints:
Use FILE * fin = fopen(...) to open the file passes as argument. See man fopen
You can determine the length of the file by using the following sequence. Fine :

1
2
3
4
// Get file size
fseek(fin, 0L, SEEK_END); // Go to the end of the file fin
int fileSize = ftell(fin); // Get current file pointer
fseek(fin, 0L, SEEK_SET); // Go back to the beginning of the file.

Allocate a large chunk of size fileSize bytes using malloc and read the whole file into it using fread.
Copy your implementation of memoryDump into myfiledump.c and modify to print using offset 0 as the beginning.

Step 7. Determine the Signature of Special Files

The first few bytes of an executable are called The Magic Number or Signature
and are used by different programs to identify the type of a file. Using your myfiledump tool find the signature for the following files as well as the extension used. Sometimes the signature shows later in the file at some known Offset but most of the time appears at the beginning (

File TypeExtensionSignatureSignature Offset
Executable file
WAV file
JPEG
GIF
TAR
ZIP

Write this table in a file signature.txt and include it in lab5-src/signature.txt

Step 8. Our Tests

Also, make sure that your program passes our tests. To run the tests, compile your program and type

./testall

or run each individual test as indicated in the output.
Make sure that all tests pass and testall gives the maximum points.

Step 9. Turning In your Project

Follow these instructions to turnin lab5:

cd cs240turnin -c cs240 -v -p lab5 lab5-src
]]>

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注