c to assembly c
play

C to assembly / C 1 last time AT&T syntax destination last - PowerPoint PPT Presentation

C to assembly / C 1 last time AT&T syntax destination last jmp * lea condition codes ZF, SF, CF, OF set by last arithmetic instruction ZF = result was zero SF = result was negative (sign bit set) CF = overfmow if treating


  1. exercise explanation 6 foo + 1 == &foo[0] + 1 pointer foo (on stack) 'b''o''z''\0' *(foo + 1) = 'a'; 8 pointer[0] = 'z'; 7 pointer = pointer + 2; *pointer = 'b'; better style: *pointer = 'z'; 5 pointer = foo; 4 char *pointer; 3 // {'f', 'o', 'o', '\0'} 2 char foo[4] = "foo"; 1 better style: foo[1] = 'a'; 23

  2. exercise explanation 6 foo + 1 == &foo[0] + 1 pointer foo (on stack) 'b''a''z''\0' *(foo + 1) = 'a'; 8 pointer[0] = 'z'; 7 pointer = pointer + 2; *pointer = 'b'; better style: *pointer = 'z'; 5 pointer = foo; 4 char *pointer; 3 // {'f', 'o', 'o', '\0'} 2 char foo[4] = "foo"; 1 better style: foo[1] = 'a'; 23

  3. arrays: not quite pointers (1) int array[100]; int *pointer; Illegal: array = pointer; 24 Legal: pointer = array; same as pointer = &(array[0]);

  4. arrays: not quite pointers (1) int array[100]; int *pointer; Illegal: 24 Legal: pointer = array; same as pointer = &(array[0]); ❤❤❤❤❤❤❤❤❤❤❤❤❤❤ ✭ ✭✭✭✭✭✭✭✭✭✭✭✭✭✭ array = pointer; ❤

  5. arrays: not quite pointers (2) int array[100]; int *pointer = array; sizeof (array) == 400 size of all elements sizeof (pointer) == 8 size of address sizeof (&array[0]) == ??? ( &array[0] same as &(array[0]) ) 25

  6. arrays: not quite pointers (2) int array[100]; int *pointer = array; sizeof (array) == 400 size of all elements sizeof (pointer) == 8 size of address sizeof (&array[0]) == ??? ( &array[0] same as &(array[0]) ) 25

  7. arrays: not quite pointers (2) int array[100]; int *pointer = array; sizeof (array) == 400 size of all elements sizeof (pointer) == 8 size of address sizeof (&array[0]) == ??? ( &array[0] same as &(array[0]) ) 25

  8. interlude: command line tips cr4bd@reiss-lenovo:~$ man man 26

  9. man man 27

  10. man man 28

  11. tar the standard Linux/Unix fjle archive utility Table of contents: tar tf filename.tar eXtract: tar xvf filename.tar Create: tar cvf filename.tar directory ( v : verbose; f : fjle — default is tape) 29

  12. tab completion and history 30

  13. stdio.h C does not have <iostream> instead <stdio.h> 31

  14. stdio and the physical I/O characteristics are efficient buffered stream I/O interface. Input and output is mapped into logical data streams concealed. simple The functions and macros are listed below; more information is available from the individual man pages. and a cr4bd@power1 SYNOPSIS : /if22/cr4bd ; man stdio … STDIO(3) Linux Programmer's Manual STDIO(3) NAME stdio - standard input/output library functions #include <stdio.h> provides FILE *stdin; FILE *stdout; FILE *stderr; DESCRIPTION The standard I/O library 32

  15. stdio clearerr … formatted output conversion printf … close a stream fclose check and reset stream status --------------------------------------------------------------- STDIO(3) Description Function List of functions … stdio - standard input/output library functions NAME STDIO(3) Linux Programmer's Manual 33

  16. format string must match types of argument printf // "Customer #1000: Jane Smith" << ": " << name << endl; 8 cout << "Customer #" << custNo 7 // same as: 6 5 1 custNo, name); 4 printf("Customer #%d: %s \n " , 3 const char *name = "Jane Smith" 2 int custNo = 1000; 34

  17. format string must match types of argument printf // "Customer #1000: Jane Smith" << ": " << name << endl; 8 cout << "Customer #" << custNo 7 // same as: 6 5 1 custNo, name); 4 printf("Customer #%d: %s \n " , 3 const char *name = "Jane Smith" 2 int custNo = 1000; 34

  18. printf // "Customer #1000: Jane Smith" format string must match types of argument << ": " << name << endl; 8 cout << "Customer #" << custNo 7 // same as: 6 5 1 custNo, name); 4 printf("Customer #%d: %s \n " , 3 const char *name = "Jane Smith" 2 int custNo = 1000; 34

  19. printf formats quick reference 4.200000e+01 %f double/fmoat 42.000000 0.000000 %e double/fmoat 4.200000e-19 long %g double/fmoat 42 , 4.2e-19 %% (no argument) % detailed docs: man 3 printf 42 %ld Specifjer 0x4005d4 Argument Type Example(s) %s char * Hello, World! %p any pointer %d 2a int/short/char 42 %u unsigned int/short/char 42 %x unsigned int/short/char 35

  20. printf formats quick reference 4.200000e+01 %f double/fmoat 42.000000 0.000000 %e double/fmoat 4.200000e-19 long %g double/fmoat 42 , 4.2e-19 %% (no argument) % detailed docs: man 3 printf 42 %ld Specifjer 0x4005d4 Argument Type Example(s) %s char * Hello, World! %p any pointer %d 2a int/short/char 42 %u unsigned int/short/char 42 %x unsigned int/short/char 35

  21. struct struct rational { int numerator; int denominator; }; // ... struct rational two_and_a_half; two_and_a_half.numerator = 5; struct rational *pointer = &two_and_a_half; printf("%d/%d \n ", pointer->numerator, pointer->denominator); 36 two_and_a_half.denominator = 2;

  22. struct struct rational { int numerator; int denominator; }; // ... struct rational two_and_a_half; two_and_a_half.numerator = 5; struct rational *pointer = &two_and_a_half; printf("%d/%d \n ", pointer->numerator, pointer->denominator); 36 two_and_a_half.denominator = 2;

  23. typedef instead of writing: ... unsigned int a; unsigned int b; unsigned int c; can write: typedef unsigned int uint; ... uint a; uint b; uint c; 37

  24. typedef struct (1) struct other_name_for_rational { int numerator; int denominator; }; typedef struct other_name_for_rational rational; // ... rational two_and_a_half; two_and_a_half.denominator = 2; printf("%d/%d \n ", pointer->numerator, pointer->denominator); 38 two_and_a_half.numerator = 5; rational *pointer = &two_and_a_half;

  25. typedef struct (1) struct other_name_for_rational { int numerator; int denominator; }; typedef struct other_name_for_rational rational; // ... rational two_and_a_half; two_and_a_half.denominator = 2; printf("%d/%d \n ", pointer->numerator, pointer->denominator); 38 two_and_a_half.numerator = 5; rational *pointer = &two_and_a_half;

  26. typedef struct (2) int denominator; } rational; int denominator; int numerator; typedef struct { // almost the same as: } rational; int numerator; struct other_name_for_rational { typedef struct other_name_for_rational { // same as: typedef struct other_name_for_rational rational; }; int denominator; int numerator; 39

  27. typedef struct (2) int denominator; } rational; int denominator; int numerator; typedef struct { // almost the same as: } rational; int numerator; struct other_name_for_rational { typedef struct other_name_for_rational { // same as: typedef struct other_name_for_rational rational; }; int denominator; int numerator; 39

  28. typedef struct (2) int denominator; } rational; int denominator; int numerator; typedef struct { // almost the same as: } rational; int numerator; struct other_name_for_rational { typedef struct other_name_for_rational { // same as: typedef struct other_name_for_rational rational; }; int denominator; int numerator; 39

  29. typedef struct (3) struct other_name_for_rational { int numerator; int denominator; }; typedef struct other_name_for_rational rational; valid ways to declare an instance: struct other_name_for_rational some_variable; rational some_variable; INVALID ways: /* INVALID: */ struct rational some_variable; /* INVALID: */ other_name_for_rational some_variable; 40

  30. structs aren’t references return address bar.a bar.b bar.c foo.a foo.b foo.c registers callee saved … typedef struct { // bar is 4, 3, 3 // foo is 3, 3, 3 triple foo; ... } triple; long a; long b; long c; 41 foo.a = foo.b = foo.c = 3; triple bar = foo; bar.a = 4;

  31. unsigned and signed types type . . . unsigned long signed long = long unsigned int = unsigned signed int = signed = int max min 42 2 31 − 1 − 2 31 2 32 − 1 0 2 63 − 1 − 2 63 2 64 − 1 0

  32. unsigned/signed comparison trap (1) int x = -1; unsigned int y = 0; printf("%d \n ", x < y); result is 0 short solution: don’t compare signed to unsigned: ( long ) x < ( long ) y 43

  33. unsigned/signed comparison trap (1) int x = -1; unsigned int y = 0; printf("%d \n ", x < y); result is 0 short solution: don’t compare signed to unsigned: ( long ) x < ( long ) y 43

  34. unsigned/signed comparison trap (1) int x = -1; unsigned int y = 0; printf("%d \n ", x < y); result is 0 short solution: don’t compare signed to unsigned: ( long ) x < ( long ) y 43

  35. unsigned/sign comparison trap (2) int x = -1; unsigned int y = 0; printf("%d \n ", x < y); int if all possible values fjt otherwise: fjrst operand ( x , y ) type from this list: unsigned long long unsigned int int 44 compiler converts both to same type fjrst

  36. adds: // comments C evolution and standards 1978: Kernighan and Ritchie publish The C Programming Language — “K&R C” very difgerent from modern C 1989: ANSI standardizes C — C89/C90/ -ansi compiler option: -ansi , -std=c90 looks mostly like modern C 1999: ISO (and ANSI) update C standard — C99 compiler option: -std=c99 adds: declare variables in middle of block 2011: Second ISO update — C11 45

  37. adds: // comments C evolution and standards 1978: Kernighan and Ritchie publish The C Programming Language — “K&R C” very difgerent from modern C 1989: ANSI standardizes C — C89/C90/ -ansi compiler option: -ansi , -std=c90 looks mostly like modern C 1999: ISO (and ANSI) update C standard — C99 compiler option: -std=c99 adds: declare variables in middle of block 2011: Second ISO update — C11 45

  38. C evolution and standards 1978: Kernighan and Ritchie publish The C Programming Language — “K&R C” very difgerent from modern C 1989: ANSI standardizes C — C89/C90/ -ansi compiler option: -ansi , -std=c90 looks mostly like modern C 1999: ISO (and ANSI) update C standard — C99 compiler option: -std=c99 adds: declare variables in middle of block 2011: Second ISO update — C11 45 adds: // comments

  39. C evolution and standards 1978: Kernighan and Ritchie publish The C Programming Language — “K&R C” very difgerent from modern C 1989: ANSI standardizes C — C89/C90/ -ansi compiler option: -ansi , -std=c90 looks mostly like modern C 1999: ISO (and ANSI) update C standard — C99 compiler option: -std=c99 adds: declare variables in middle of block 2011: Second ISO update — C11 45 adds: // comments

  40. undefjned behavior example (1) #include <stdio.h> #include <limits.h> int test( int number) { return (number + 1) > number; } int main( void ) { printf("%d \n ", test(INT_MAX)); } without optimizations: 0 with optimizations: 1 46

  41. undefjned behavior example (1) #include <stdio.h> #include <limits.h> int test( int number) { return (number + 1) > number; } int main( void ) { printf("%d \n ", test(INT_MAX)); } without optimizations: 0 with optimizations: 1 46

  42. undefjned behavior example (1) #include <stdio.h> #include <limits.h> int test( int number) { return (number + 1) > number; } int main( void ) { printf("%d \n ", test(INT_MAX)); } without optimizations: 0 with optimizations: 1 46

  43. undefjned behavior example (2) test: ret %al, %eax movzbl %al setl %eax, %edi cmpl int test( int number) { leal Less optimized: ret $1, %eax movl test: Optimized: } return (number + 1) > number; 47 # eax ← 1 1(%rdi), %eax # eax ← rdi + 1 # al ← eax < edi # eax ← al (pad with zeros)

  44. undefjned behavior compilers can do whatever they want what you expect crash your program … common types: signed integer overfmow/underfmow out-of-bounds pointers integer divide-by-zero writing read-only data out-of-bounds shift 48

  45. undefjned behavior why undefjned behavior? difgerent architectures work difgerently allow compilers to expose whatever processor does “naturally” don’t encode any particular machine in the standard fmexibility for optimizations 49

  46. extracting hexadecimal nibble (1) typedef unsigned char byte; int get_top_nibble(byte value) { return ???; } problem: given 0xAB extract 0xA (hexadecimal digits called “nibbles”) 50

  47. extracing hexadecimal nibbles (2) typedef unsigned char byte; int get_top_nibble(byte value) { return value / 16; } 51

  48. aside: division division is really slow Intel “Skylake” microarchitecture: …and much worse for eight-byte division but this case: it’s just extracting ‘top wires’ — simpler? 52 about six cycles per division versus: four additions per cycle

  49. aside: division division is really slow Intel “Skylake” microarchitecture: …and much worse for eight-byte division but this case: it’s just extracting ‘top wires’ — simpler? 52 about six cycles per division versus: four additions per cycle

  50. extracting bits in hardware 0111 0010 = 0x72 7 53 0 1 1 1 0 0 1 0

  51. exposing wire selection 1 0 0 0 0 0 0 0 0 ? ? ? ? 1 1 1 1 1 0 x86 instruction: shr — shift right 0 shr $ amount , %reg (or variable: shr %cl, %reg ) %reg (initial value) %reg (fjnal value) 0 0 0 0 0 0 … … … … 54 0 0 1 0

  52. exposing wire selection 1 0 0 0 0 0 0 0 0 ? ? ? ? 1 1 1 1 1 0 x86 instruction: shr — shift right 0 shr $ amount , %reg (or variable: shr %cl, %reg ) %reg (initial value) %reg (fjnal value) 0 0 0 0 0 0 … … … … 54 0 0 1 0

  53. exposing wire selection 1 0 0 0 0 0 0 0 0 ? ? ? ? 1 1 1 1 1 0 x86 instruction: shr — shift right 0 shr $ amount , %reg (or variable: shr %cl, %reg ) %reg (initial value) %reg (fjnal value) 0 0 0 0 0 0 … … … … 54 0 0 1 0

  54. shift right x86 instruction: shr — shift right shr $ amount , %reg get_top_nibble: movzbl %dil, %eax shrl $4, %eax ret 55 (or variable: shr %cl, %reg ) // eax ← dil (low byte of rdi) w/ zero padding

  55. shift right x86 instruction: shr — shift right shr $ amount , %reg get_top_nibble: movzbl %dil, %eax shrl $4, %eax ret 55 (or variable: shr %cl, %reg ) // eax ← dil (low byte of rdi) w/ zero padding

  56. shift right x86 instruction: shr — shift right shr $ amount , %reg get_top_nibble: movzbl %dil, %eax shrl $4, %eax ret 55 (or variable: shr %cl, %reg ) // eax ← dil (low byte of rdi) w/ zero padding

  57. right shift in C get_top_nibble: movzbl %dil, %eax shrl $4, %eax ret typedef unsigned char byte; int get_top_nibble(byte value) { return value >> 4; } 56 // eax ← dil (low byte of rdi) w/ zero padding

  58. right shift in C typedef unsigned char byte; int get_top_nibble1(byte value) { return value >> 4; } int get_top_nibble2(byte value) { return value / 16; } example output from optimizing compiler: get_top_nibble1: shrb $4, %dil movzbl %dil, %eax ret get_top_nibble2: shrb $4, %dil movzbl %dil, %eax ret 57

  59. right shift in C typedef unsigned char byte; int get_top_nibble1(byte value) { return value >> 4; } int get_top_nibble2(byte value) { return value / 16; } example output from optimizing compiler: get_top_nibble1: shrb $4, %dil movzbl %dil, %eax ret get_top_nibble2: shrb $4, %dil movzbl %dil, %eax ret 57

  60. right shift in math 1 >> 0 == 1 0000 0001 1 >> 1 == 0 0000 0000 1 >> 2 == 0 0000 0000 10 >> 0 == 10 0000 1010 10 >> 1 == 5 0000 0101 10 >> 2 == 2 0000 0010 58 � x × 2 − y � x >> y =

  61. exercise int foo(int) foo: movl %edi, %eax shrl $1, %eax ret what is the value of foo(-2) ? A. -4 B. -2 C. -1 D. 0 E. a small positive number F. a large positive number G. a large negative number H. something else 59

  62. two’s complement refresher 1 1111 1111 … 1111 1000 0000 … 0000 0111 1111 … 1111 1 1 60 1 … 1 1 − 2 31 +2 30 +2 29 +2 2 +2 1 +2 0 − 1 =

Recommend


More recommend