summaryrefslogtreecommitdiff
path: root/3
diff options
context:
space:
mode:
authorMike Vink <mike@pionative.com>2024-06-14 09:23:32 +0200
committerMike Vink <mike@pionative.com>2024-06-14 09:23:32 +0200
commit8092f4c334db547ced59d6f439b558dad35e1ab2 (patch)
treefa462fa885efea1ec6095d015286998d632c2c3d /3
parentb424517a33bf61aedff29eed74a665402ab496ba (diff)
commit for once
Diffstat (limited to '3')
-rw-r--r--3/10_control_and_data/00_prog.c0
-rw-r--r--3/10_control_and_data/01_echo.c24
-rw-r--r--3/10_control_and_data/46_get_line.c31
-rw-r--r--3/10_control_and_data/47_address_range.c10
-rw-r--r--3/10_control_and_data/48_stack_protection.c52
-rw-r--r--3/10_control_and_data/49_variable_stack.c81
-rw-r--r--3/11_floating_point/00_float_mov.c11
-rw-r--r--3/11_floating_point/01_fcvt.c17
-rw-r--r--3/11_floating_point/fcvt.s154
-rw-r--r--3/7_procedures/35_rfun.c25
-rw-r--r--3/8_array_allocation_and_access/36_sizes_and_addresses.c11
-rw-r--r--3/8_array_allocation_and_access/37_array_arithmetic.c7
-rw-r--r--3/8_array_allocation_and_access/38_nested_arrays.c18
-rw-r--r--3/8_array_allocation_and_access/39_explain_rows_cols.c8
-rw-r--r--3/8_array_allocation_and_access/40_diagonal_elements.c48
-rw-r--r--3/9_data_structures/41_struct_test.c30
-rw-r--r--3/9_data_structures/42_ace_structure.c23
-rw-r--r--3/9_data_structures/43_dest.c43
-rw-r--r--3/9_data_structures/44_gaps.c86
-rw-r--r--3/9_data_structures/45_rec.c42
20 files changed, 721 insertions, 0 deletions
diff --git a/3/10_control_and_data/00_prog.c b/3/10_control_and_data/00_prog.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/3/10_control_and_data/00_prog.c
diff --git a/3/10_control_and_data/01_echo.c b/3/10_control_and_data/01_echo.c
new file mode 100644
index 0000000..8ef71e2
--- /dev/null
+++ b/3/10_control_and_data/01_echo.c
@@ -0,0 +1,24 @@
+#include <stdio.h>
+
+char* gets(char *s) {
+ int c;
+ char *dest = s;
+ while ((c = getchar()) != '\n' && c != EOF) {
+ *dest++ = c;
+ }
+ if ( c == EOF && dest == s) {
+ return NULL;
+ }
+ *dest++ = '\0';
+ return s;
+}
+
+void echo() {
+ char buf[8];
+ gets(buf);
+ puts(buf);
+}
+
+int main(void) {
+ echo();
+}
diff --git a/3/10_control_and_data/46_get_line.c b/3/10_control_and_data/46_get_line.c
new file mode 100644
index 0000000..f1920e8
--- /dev/null
+++ b/3/10_control_and_data/46_get_line.c
@@ -0,0 +1,31 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+// char *get_line()
+// 400720: 53 push %rbx
+// 400721: 48 83 ec 10 sub $0x10,%rsp
+// 400725: 48 89 e7 mov %rsp,%rdi
+// 400728 e8 73 ff ff ff callq 4006a0 <gets>
+char *get_line() {
+ char buf[4];
+ char *result;
+ gets(buf);
+ result = malloc(strlen(buf));
+ strcpy(result, buf);
+ return result;
+}
+int main(void) {
+ printf("%s\n", get_line());
+}
+// A. B. (I mistakingly thought $0x10 was the same as $10...)
+// 00 34 33 32 31 30 39 38 return address
+// 37 36 35 34 33 32 31 30 callee saved %rbx
+// 39 38 37 36 35 34 33 32< sub $rsp - 8
+// 31 30 00 00 00 00 00 40 sub $rsp -16
+// 07 32< return address gets
+//
+// C. 00 34 33 32 31 30 39 38
+// D. %rbx
+// E. Malloc should consider the terminating null (strlen+1) and check for NULL pointer result
diff --git a/3/10_control_and_data/47_address_range.c b/3/10_control_and_data/47_address_range.c
new file mode 100644
index 0000000..57a3fcb
--- /dev/null
+++ b/3/10_control_and_data/47_address_range.c
@@ -0,0 +1,10 @@
+//
+// A. Using bc
+//
+ibase=16; FFFFB754
+ibase=16; FFFFD754 - FFFFB754
+8192
+2^13
+// B.
+2^5
+32
diff --git a/3/10_control_and_data/48_stack_protection.c b/3/10_control_and_data/48_stack_protection.c
new file mode 100644
index 0000000..08cb4e8
--- /dev/null
+++ b/3/10_control_and_data/48_stack_protection.c
@@ -0,0 +1,52 @@
+int len(char *s) {
+ return strlen(s);
+}
+
+void iptoa(char *s, long *p) {
+ long val = *p;
+ sprintf(s, "%ld", val);
+}
+
+// int inlen(long x)
+// x in %rdi
+// without canary
+//
+// intlen:
+// subq $40, %rsp allocate 5*8 bytes
+// movq %rdi, 24(%rsp) put x on the stack
+// leaq 24(%rsp), %rsi set &v = &x to the second argument
+// movq %rsp, %rdi set buf[12] to %rsp
+// call iptoa
+//
+// 0<rsp+32 <-?
+// 0<rsp+24 <-v
+// 0<rsp+16 <-?
+// 0<rsp+8 <-buf[12]
+// 0<rsp <-buf[12]
+//
+// with canary
+//
+// intlen:
+// subq $56, %rsp
+// movq %fs:40, %rax
+// movq %rax, 40(%rsp)
+// xorl %eax, %eax
+// movq %rdi, 8(%rsp)
+// leaq 8(%rsp), %rsi
+// leaq 16(%rsp), %rdi
+// call iptoa
+//
+// 0<rsp+48 <-
+// 0<rsp+40 <-canary
+// 0<rsp+32 <-
+// 0<rsp+24 <-
+// 0<rsp+16 <-buf[12]
+// 0<rsp+8 <-v
+// 0<rsp <-
+int intlen(long x) {
+ long v;
+ char buf[12];
+ v = x;
+ iptoa(buf, &v);
+ return len(buf);
+}
diff --git a/3/10_control_and_data/49_variable_stack.c b/3/10_control_and_data/49_variable_stack.c
new file mode 100644
index 0000000..d72c235
--- /dev/null
+++ b/3/10_control_and_data/49_variable_stack.c
@@ -0,0 +1,81 @@
+// A.
+// vframe:
+// pushq %rbp
+// movq %rsp, %rbp
+// subq $16, %rsp
+// leaq 22(,%rdi,8), %rax
+// andq $-16, %rax
+//
+//
+// bitlevel representation of -16
+// 1111111111111111111111111111111111111111111111111111111111110000
+//
+// rax
+// 22 + n*8
+// n=0 0000000000000000000000000000000000000000000000000000000000010110 22
+// n=1 0000000000000000000000000000000000000000000000000000000000011110 30
+// n=2 0000000000000000000000000000000000000000000000000000000000100110 38
+// n=3 0000000000000000000000000000000000000000000000000000000000101110 46
+// n=4 0000000000000000000000000000000000000000000000000000000000110110 54
+// n=5 0000000000000000000000000000000000000000000000000000000000111110 62
+//
+// (22 + n*8) & -16
+// n=0 0000000000000000000000000000000000000000000000000000000000010000 16 8n+16
+// n=1 0000000000000000000000000000000000000000000000000000000000010000 16 8n+8
+// n=2 0000000000000000000000000000000000000000000000000000000000100000 32 8n+16
+// n=3 0000000000000000000000000000000000000000000000000000000000100000 32 8n+8
+// n=4 0000000000000000000000000000000000000000000000000000000000110000 48
+// n=5 0000000000000000000000000000000000000000000000000000000000110000 48
+//
+// print("{:064b}".format((0*8+22) & -16))
+// print("{:064b}".format((1*8+22) & -16))
+// print("{:064b}".format((2*8+22) & -16))
+// print("{:064b}".format((3*8+22) & -16))
+// print("{:064b}".format((4*8+22) & -16))
+// print("{:064b}".format((5*8+22) & -16))
+//
+// B.
+// vframe:
+// pushq %rbp
+// movq %rsp, %rbp
+// subq $16, %rsp
+// leaq 22(,%rdi,8), %rax
+// andq $-16, %rax
+//
+// subq %rax, %rsp
+//
+// leaq 7(%rsp), %rax rax <- (rsp+7) = (rsp+(n-1)), n = 8
+// shrq $3, %rax rax <- (floor(rax/8))
+// leaq 0(,%rax,8), %r8 r8 <- ceil(rsp/8)*8
+//
+// Important We are growing the stack downwards.
+// But the array index grows upwards.
+//
+// See 2.3.7 for derivation.
+// If x%(1<<k) == 0 then the bias has no effect, rounding down does not happen, there is no fraction.
+// else
+// Since the operation of adding the bias and then flooring happens,
+// this results in rounding towards zero, or taking the ceiling.
+//
+// So if rsp was a multiple of 8 then nothing happens.
+// Otherwise the start of the array is set to the first multiple of 8 towards the bottom of the stack (ceil goes towards greater addresses of the bottom).
+//
+// C.
+//
+// s_2 = (- s_1
+// (+ (if (odd? n) 8 16) (* n 8) )
+// )
+//
+// p = ceil(s2/8)*8
+// e2 = (- p s2)
+// e1 = (- s2 s1 e2 8n)
+//
+// 2065 - (8+5*8)
+//
+// n s_1 s_2 p e_1 e_2
+// 5 2065 2017 2024 1 7
+// 6 2064 2000 2000 16 0
+//
+// D.
+// p is 8byte aligned owing to the 8-10 instructions.
+// s2 is not guaranteed to be aligned, so 1 byte. (But all we are doing is subtracting multiples of 16 from s1... not sure how this helps)
diff --git a/3/11_floating_point/00_float_mov.c b/3/11_floating_point/00_float_mov.c
new file mode 100644
index 0000000..dd0379d
--- /dev/null
+++ b/3/11_floating_point/00_float_mov.c
@@ -0,0 +1,11 @@
+// v1 in %xmm0, src in %rdi, dst in %rsi
+// float_mov:
+// vmovaps %xmm0, %xmm1 Copy v1
+// vmovss (%rdi), %xmm0 Read v2 from src
+// vmovss %xmm1, (%rsi) Write v1 to dst
+// ret;
+float float_mov(float v1, float *src, float *dst) {
+ float v2 = *src;
+ *dst = v1;
+ return v2;
+}
diff --git a/3/11_floating_point/01_fcvt.c b/3/11_floating_point/01_fcvt.c
new file mode 100644
index 0000000..a75ff48
--- /dev/null
+++ b/3/11_floating_point/01_fcvt.c
@@ -0,0 +1,17 @@
+#include <stdio.h>
+double fcvt(int i, float *fp, double *dp, long *lp) {
+ float f = *fp; double d = *dp; long l = *lp;
+ *lp = (long) d; // double->long
+ *fp = (float) i; // int->float
+ *dp = (double) l; // long->double
+ return (double) f; // float->double
+}
+
+int main(void) {
+ float f = 0.5f; double d = 1.0; long l = 1;
+
+ float *fp = &f; double *dp = &d; long *lp = &l;
+
+ fcvt(42, fp, dp, lp);
+ return 0;
+}
diff --git a/3/11_floating_point/fcvt.s b/3/11_floating_point/fcvt.s
new file mode 100644
index 0000000..c7a3117
--- /dev/null
+++ b/3/11_floating_point/fcvt.s
@@ -0,0 +1,154 @@
+
+./fcvt: file format elf64-x86-64
+
+
+Disassembly of section .init:
+
+0000000000401000 <_init>:
+ 401000: f3 0f 1e fa endbr64
+ 401004: 48 83 ec 08 sub $0x8,%rsp
+ 401008: 48 8b 05 e9 2f 00 00 mov 0x2fe9(%rip),%rax # 403ff8 <__gmon_start__@Base>
+ 40100f: 48 85 c0 test %rax,%rax
+ 401012: 74 02 je 401016 <_init+0x16>
+ 401014: ff d0 call *%rax
+ 401016: 48 83 c4 08 add $0x8,%rsp
+ 40101a: c3 ret
+
+Disassembly of section .plt:
+
+0000000000401020 <__stack_chk_fail@plt-0x10>:
+ 401020: ff 35 b2 2f 00 00 push 0x2fb2(%rip) # 403fd8 <_GLOBAL_OFFSET_TABLE_+0x8>
+ 401026: ff 25 b4 2f 00 00 jmp *0x2fb4(%rip) # 403fe0 <_GLOBAL_OFFSET_TABLE_+0x10>
+ 40102c: 0f 1f 40 00 nopl 0x0(%rax)
+
+0000000000401030 <__stack_chk_fail@plt>:
+ 401030: ff 25 b2 2f 00 00 jmp *0x2fb2(%rip) # 403fe8 <__stack_chk_fail@GLIBC_2.4>
+ 401036: 68 00 00 00 00 push $0x0
+ 40103b: e9 e0 ff ff ff jmp 401020 <_init+0x20>
+
+Disassembly of section .text:
+
+0000000000401040 <_start>:
+ 401040: f3 0f 1e fa endbr64
+ 401044: 31 ed xor %ebp,%ebp
+ 401046: 49 89 d1 mov %rdx,%r9
+ 401049: 5e pop %rsi
+ 40104a: 48 89 e2 mov %rsp,%rdx
+ 40104d: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp
+ 401051: 50 push %rax
+ 401052: 54 push %rsp
+ 401053: 45 31 c0 xor %r8d,%r8d
+ 401056: 31 c9 xor %ecx,%ecx
+ 401058: 48 c7 c7 4f 11 40 00 mov $0x40114f,%rdi
+ 40105f: ff 15 8b 2f 00 00 call *0x2f8b(%rip) # 403ff0 <__libc_start_main@GLIBC_2.34>
+ 401065: f4 hlt
+ 401066: 66 2e 0f 1f 84 00 00 cs nopw 0x0(%rax,%rax,1)
+ 40106d: 00 00 00
+
+0000000000401070 <_dl_relocate_static_pie>:
+ 401070: f3 0f 1e fa endbr64
+ 401074: c3 ret
+ 401075: 66 2e 0f 1f 84 00 00 cs nopw 0x0(%rax,%rax,1)
+ 40107c: 00 00 00
+ 40107f: 90 nop
+
+0000000000401080 <deregister_tm_clones>:
+ 401080: b8 10 40 40 00 mov $0x404010,%eax
+ 401085: 48 3d 10 40 40 00 cmp $0x404010,%rax
+ 40108b: 74 13 je 4010a0 <deregister_tm_clones+0x20>
+ 40108d: b8 00 00 00 00 mov $0x0,%eax
+ 401092: 48 85 c0 test %rax,%rax
+ 401095: 74 09 je 4010a0 <deregister_tm_clones+0x20>
+ 401097: bf 10 40 40 00 mov $0x404010,%edi
+ 40109c: ff e0 jmp *%rax
+ 40109e: 66 90 xchg %ax,%ax
+ 4010a0: c3 ret
+ 4010a1: 66 66 2e 0f 1f 84 00 data16 cs nopw 0x0(%rax,%rax,1)
+ 4010a8: 00 00 00 00
+ 4010ac: 0f 1f 40 00 nopl 0x0(%rax)
+
+00000000004010b0 <register_tm_clones>:
+ 4010b0: be 10 40 40 00 mov $0x404010,%esi
+ 4010b5: 48 81 ee 10 40 40 00 sub $0x404010,%rsi
+ 4010bc: 48 89 f0 mov %rsi,%rax
+ 4010bf: 48 c1 ee 3f shr $0x3f,%rsi
+ 4010c3: 48 c1 f8 03 sar $0x3,%rax
+ 4010c7: 48 01 c6 add %rax,%rsi
+ 4010ca: 48 d1 fe sar %rsi
+ 4010cd: 74 11 je 4010e0 <register_tm_clones+0x30>
+ 4010cf: b8 00 00 00 00 mov $0x0,%eax
+ 4010d4: 48 85 c0 test %rax,%rax
+ 4010d7: 74 07 je 4010e0 <register_tm_clones+0x30>
+ 4010d9: bf 10 40 40 00 mov $0x404010,%edi
+ 4010de: ff e0 jmp *%rax
+ 4010e0: c3 ret
+ 4010e1: 66 66 2e 0f 1f 84 00 data16 cs nopw 0x0(%rax,%rax,1)
+ 4010e8: 00 00 00 00
+ 4010ec: 0f 1f 40 00 nopl 0x0(%rax)
+
+00000000004010f0 <__do_global_dtors_aux>:
+ 4010f0: f3 0f 1e fa endbr64
+ 4010f4: 80 3d 15 2f 00 00 00 cmpb $0x0,0x2f15(%rip) # 404010 <__TMC_END__>
+ 4010fb: 75 13 jne 401110 <__do_global_dtors_aux+0x20>
+ 4010fd: 55 push %rbp
+ 4010fe: 48 89 e5 mov %rsp,%rbp
+ 401101: e8 7a ff ff ff call 401080 <deregister_tm_clones>
+ 401106: c6 05 03 2f 00 00 01 movb $0x1,0x2f03(%rip) # 404010 <__TMC_END__>
+ 40110d: 5d pop %rbp
+ 40110e: c3 ret
+ 40110f: 90 nop
+ 401110: c3 ret
+ 401111: 66 66 2e 0f 1f 84 00 data16 cs nopw 0x0(%rax,%rax,1)
+ 401118: 00 00 00 00
+ 40111c: 0f 1f 40 00 nopl 0x0(%rax)
+
+0000000000401120 <frame_dummy>:
+ 401120: f3 0f 1e fa endbr64
+ 401124: eb 8a jmp 4010b0 <register_tm_clones>
+
+0000000000401126 <fcvt>:
+ 401126: c5 f0 57 c9 vxorps %xmm1,%xmm1,%xmm1
+ 40112a: c5 fa 10 06 vmovss (%rsi),%xmm0
+ 40112e: 48 8b 01 mov (%rcx),%rax
+ 401131: c4 61 fb 2c 02 vcvttsd2si (%rdx),%r8
+ 401136: 4c 89 01 mov %r8,(%rcx)
+ 401139: c5 f2 2a d7 vcvtsi2ss %edi,%xmm1,%xmm2
+ 40113d: c5 fa 11 16 vmovss %xmm2,(%rsi)
+ 401141: c4 e1 f3 2a c8 vcvtsi2sd %rax,%xmm1,%xmm1
+ 401146: c5 fb 11 0a vmovsd %xmm1,(%rdx)
+ 40114a: c5 fa 5a c0 vcvtss2sd %xmm0,%xmm0,%xmm0
+ 40114e: c3 ret
+
+000000000040114f <main>:
+ 40114f: 48 83 ec 28 sub $0x28,%rsp
+ 401153: 64 48 8b 04 25 28 00 mov %fs:0x28,%rax
+ 40115a: 00 00
+ 40115c: 48 89 44 24 18 mov %rax,0x18(%rsp)
+ 401161: 31 c0 xor %eax,%eax
+ 401163: c7 44 24 04 00 00 00 movl $0x3f000000,0x4(%rsp)
+ 40116a: 3f
+ 40116b: 48 8b 05 96 0e 00 00 mov 0xe96(%rip),%rax # 402008 <_IO_stdin_used+0x8>
+ 401172: 48 89 44 24 08 mov %rax,0x8(%rsp)
+ 401177: 48 c7 44 24 10 01 00 movq $0x1,0x10(%rsp)
+ 40117e: 00 00
+ 401180: 48 8d 4c 24 10 lea 0x10(%rsp),%rcx
+ 401185: 48 8d 54 24 08 lea 0x8(%rsp),%rdx
+ 40118a: 48 8d 74 24 04 lea 0x4(%rsp),%rsi
+ 40118f: bf 2a 00 00 00 mov $0x2a,%edi
+ 401194: e8 8d ff ff ff call 401126 <fcvt>
+ 401199: 48 8b 44 24 18 mov 0x18(%rsp),%rax
+ 40119e: 64 48 2b 04 25 28 00 sub %fs:0x28,%rax
+ 4011a5: 00 00
+ 4011a7: 75 0a jne 4011b3 <main+0x64>
+ 4011a9: b8 00 00 00 00 mov $0x0,%eax
+ 4011ae: 48 83 c4 28 add $0x28,%rsp
+ 4011b2: c3 ret
+ 4011b3: e8 78 fe ff ff call 401030 <__stack_chk_fail@plt>
+
+Disassembly of section .fini:
+
+00000000004011b8 <_fini>:
+ 4011b8: f3 0f 1e fa endbr64
+ 4011bc: 48 83 ec 08 sub $0x8,%rsp
+ 4011c0: 48 83 c4 08 add $0x8,%rsp
+ 4011c4: c3 ret
diff --git a/3/7_procedures/35_rfun.c b/3/7_procedures/35_rfun.c
new file mode 100644
index 0000000..f923366
--- /dev/null
+++ b/3/7_procedures/35_rfun.c
@@ -0,0 +1,25 @@
+// x in %rdi
+// rfun:
+// pushq %rbx save rbx, since we use it and in case we are called
+// movq %rdi, %rbx %rbx <- x
+// movl $0 %rax <- 0
+// testq %rdi, %rdi ZF <- %rdi == 0
+// je .L2 jump to if ZF
+// shrq $2, %rdi shift x to the lift by 2 bits (divide by four)
+// call rfun
+// addq %rbx, %rax add our calculation to the rest
+// .L2
+// popq %rbx set rbx back to the value of our caller's calculation
+// ret
+//
+// A>
+// The value x is stored in rbx, and each iteration stores (int64_t) x/4
+// B>
+long rfun(unsigned long x) {
+ if (x == 0) {
+ return 0;
+ }
+ unsigned long nx = x>>2;
+ long rv = rfun(nx);
+ return x + rv;
+}
diff --git a/3/8_array_allocation_and_access/36_sizes_and_addresses.c b/3/8_array_allocation_and_access/36_sizes_and_addresses.c
new file mode 100644
index 0000000..c9b8056
--- /dev/null
+++ b/3/8_array_allocation_and_access/36_sizes_and_addresses.c
@@ -0,0 +1,11 @@
+// size total size start address element i
+short S[7];
+// 2 14 x_s xs + 2 * i
+short *T[3];
+// 8 24 x_t x_t + 8 * i
+short **U[6];
+// 8 48 x_u x_u + 8 * i
+int V[8];
+// 4 32 x_v x_v + 4 * i
+double *W[4];
+// 8 32 x_w x_w + 8 * i
diff --git a/3/8_array_allocation_and_access/37_array_arithmetic.c b/3/8_array_allocation_and_access/37_array_arithmetic.c
new file mode 100644
index 0000000..c2ecbf2
--- /dev/null
+++ b/3/8_array_allocation_and_access/37_array_arithmetic.c
@@ -0,0 +1,7 @@
+// S and i in rdx and rcx
+// type value assembly
+// S+1 short * xs + 2 leaq $2(%rdx), %rax, // leaq since we want to store the address not the value
+// S[3] short M[xs+6] movw $6(%rdx), %ax
+// &S[i] short * xs+2i leaq (rdx, rcx, 2), %rax
+// S[4*i+1] short M[xs+8i+2] movw $2(%rdx, %rcx, 8), %ax
+// S+i-5 short * xs+2i-10 leaq $-10(%rdx, %rcx, 2), %rax
diff --git a/3/8_array_allocation_and_access/38_nested_arrays.c b/3/8_array_allocation_and_access/38_nested_arrays.c
new file mode 100644
index 0000000..b53c7be
--- /dev/null
+++ b/3/8_array_allocation_and_access/38_nested_arrays.c
@@ -0,0 +1,18 @@
+#define M 20;
+#define N 30;
+
+long P[5][7];
+long Q[7][5];
+
+// i in rdi, j in rsi
+// sum_element:
+// leaq 0(,%rdi, 8), %rdx %rdx <- 8*i
+// subq %rdi, %rdx %rdx <- %rdx - i
+// addq %rsi, %rdx %rdx <- %rdx + j
+// leaq (%rsi, %rsi, 4), %rax %rax <- 5j
+// addq %rax, %rdi %rdi <- %rax + %rdi // rdi <- 5j + i
+// movq Q(, %rdi, 8), %rax %rax <- xq + 8(5j + i)
+// addq P(, %rdx, 8), %rax %rax <- %rax + xp + 8(7i + j)
+long sum_element(long i, long j) {
+ return P[i][j] + Q[j][i];
+}
diff --git a/3/8_array_allocation_and_access/39_explain_rows_cols.c b/3/8_array_allocation_and_access/39_explain_rows_cols.c
new file mode 100644
index 0000000..7304f23
--- /dev/null
+++ b/3/8_array_allocation_and_access/39_explain_rows_cols.c
@@ -0,0 +1,8 @@
+// addq %rdx, %rdi Aptr = xa + 64i
+// fix_matrix = int[16][16], so each int is 4 bytes and we need to multiple by the number of columns to find the
+// i row, A + L(C*i + j) <=> A + 4(16*i)
+//
+// leaq (%rsi, %rcx, 4), %rcx Bptr = xb + 4k, this one is simple B + L(C*i + j) <=> B + 4(j), find the first row of the column j
+//
+// leaq 1024(%rcx), %rsi Bend = xb + 4k + 1024, find the N row of column k,
+// B + 4(16*16 + k) <=> B + 1024 + 4k
diff --git a/3/8_array_allocation_and_access/40_diagonal_elements.c b/3/8_array_allocation_and_access/40_diagonal_elements.c
new file mode 100644
index 0000000..ab541db
--- /dev/null
+++ b/3/8_array_allocation_and_access/40_diagonal_elements.c
@@ -0,0 +1,48 @@
+// A in rdi, val in rsi
+// fix_set_diag:
+// movl $0, %eax
+// .L13
+// movl %esi, (%rdi, %rax)
+// addq $68, %rax
+// cmpq $1088, %rax
+// jne .L13
+// rep; ret
+#include <stdio.h>
+#define N 16
+typedef int fix_matrix[N][N];
+
+void fix_set_diag(fix_matrix A, int val) {
+ long i;
+ for (i = 0; i < N; i++) {
+ A[i][i] = val;
+ }
+}
+
+void fix_set_diag_opt(fix_matrix A, int val) {
+ int *Aptr = &A[0][0];
+ int *Aend = &A[N][N];
+ do {
+ *Aptr = val;
+ Aptr += N; // Next row
+ Aptr ++; // Next column
+ } while (Aptr != Aend);
+}
+
+int main(void) {
+ int i, j;
+ fix_matrix A;
+ for (i=0; i < N; i++) {
+ for (j=0; j < N; j++) {
+ A[i][j] = 0;
+ }
+ }
+
+ i, j = 0, 0;
+ fix_set_diag_opt(A, 1);
+ for (i=0; i < N; i++) {
+ for (j=0; j < N; j++) {
+ printf("%ld", A[i][j]);
+ }
+ printf("\n");
+ }
+}
diff --git a/3/9_data_structures/41_struct_test.c b/3/9_data_structures/41_struct_test.c
new file mode 100644
index 0000000..1816b31
--- /dev/null
+++ b/3/9_data_structures/41_struct_test.c
@@ -0,0 +1,30 @@
+struct test {
+ short *p;
+ struct {
+ short x;
+ short y;
+ } s;
+ struct test *next;
+}
+
+// A.
+// p: 0, it's at the beginning of the struct
+// s.x: (length p) <- 8
+// s.y: (length p) + (length s.x) <- 10
+// next: (length p) + (length s.x) + (length s.y) <- 12
+// B.
+// total bytes should be 20. pointer + short + short + pointer
+// C.
+// st in %rdi
+// st_init:
+// movl 8(%rdi), %eax
+// movl %eax, 10(%rdi)
+// leaq 10(%rdi), %rax
+// movq %rax, (%rdi)
+// movq %rdi, 12(%rdi)
+// ret
+void st_init(struct test *st) {
+ st->s.y = st->s.x;
+ st->p = &(st->s.y);
+ st->next = st;
+}
diff --git a/3/9_data_structures/42_ace_structure.c b/3/9_data_structures/42_ace_structure.c
new file mode 100644
index 0000000..8b4e92d
--- /dev/null
+++ b/3/9_data_structures/42_ace_structure.c
@@ -0,0 +1,23 @@
+#include <stdio.h>
+
+struct ACE {
+ short v;
+ struct ACE *p;
+};
+
+// B. it's a linked list of short values that are multiplied.
+short test(struct ACE *ptr) {
+ short v = 1;
+ while (ptr) {
+ v *= ptr->v;
+ ptr = ptr->p;
+ }
+ return v;
+}
+
+int main(void) {
+ struct ACE a = {2, NULL};
+ struct ACE b = {3, NULL};
+ a.p = &b;
+ printf("%d\n", test(&a));
+}
diff --git a/3/9_data_structures/43_dest.c b/3/9_data_structures/43_dest.c
new file mode 100644
index 0000000..67bb630
--- /dev/null
+++ b/3/9_data_structures/43_dest.c
@@ -0,0 +1,43 @@
+#define type long;
+
+typedef union {
+ struct {
+ long u;
+ short v;
+ char w;
+ } t1;
+ struct {
+ int a[2];
+ char *p;
+ } t2;
+} u_type;
+
+// Kinda confused when I'm moving a memory address
+// Forgot it was a union
+// Also forgot I had to move to dest
+//
+// up and dest in rdi and rsi
+//
+// expr type code
+//
+// up->t1.u long movq (%rdi), %rax
+// movq %rax, (%rsi)
+//
+// up->t1.v short movw 8(%rdi), %ax
+// movw %ax, (%rsi)
+//
+// &up->t1.w char* addq 10, %rdi
+// movq %rdi, (%rsi)
+//
+// up->t2.a int * movq %rdi, (%rsi)
+//
+// up->t2.a[up->t1.u] int movq (%rdi), %rax // What's interesting: rdi is the t2.a int* and the t1.u long, and they are being used in the same expression!
+// movl (%rdi, %rax, 4), %eax
+// movl %eax, (%rsi)
+//
+// *up->t2.p char movq 8(%rdi), %rax
+// movb (%rax), %al // Remember, you cannot have Memory -- Memory moves!
+// movb %al, (%rsi)
+void get(u_type *up, type *dest) {
+ *dest = ___;
+}
diff --git a/3/9_data_structures/44_gaps.c b/3/9_data_structures/44_gaps.c
new file mode 100644
index 0000000..1162895
--- /dev/null
+++ b/3/9_data_structures/44_gaps.c
@@ -0,0 +1,86 @@
+// A.
+struct P1 {
+ int i;
+ char c;
+ int j;
+ char d;
+};
+// Largest primitive is 4, so the local alignment value must be 4
+// |int 4| char 1|gap 3 |int 4 |char 1|gap 3|
+// |-----|--------------|------|------------|
+// 4 4 4 4
+// i 0
+// c 4
+// j 8
+// d 12
+//
+// total 16
+//
+// B.
+struct P2 {
+ int i;
+ char c;
+ char d;
+ long j;
+};
+// Largest primitive is 8, so the local alignment value must be 8
+// |int 4|char 1| char 1|gap 2|long 8|
+// |--------------------------|------|
+// 8 8
+// i 0
+// c 4
+// d 5
+// j 8
+//
+// total 16
+//
+// C.
+struct P3 {
+ short w[3];
+ char c[3];
+};
+// Largest primitive is 2, so the local alignment value must be 2
+// |short 2|short 2|short 2|char 1|char 1|char 1|gap 1|
+// |-------|-------|-------|-------------|------------|
+// 2 2 2 2 2
+//
+// w[0] 0
+// w[1] 2
+// w[2] 4
+// c[0] 6
+// c[1] 7
+// c[2] 8
+//
+// total 10
+//
+// D.
+struct P4 {
+ short w[5];
+ char *c[3];
+};
+// Largest primitive is 8, so the local alignment value must be 8
+// |short 2|short 2|short 2|short 2|short 2|gap 6|char* 8|char* 8|char* 8|
+// |-------------------------------|-------------|-------|-------|-------|
+// 8 8 8 8 8
+//
+// w[0] 0
+// w[1] 2
+// w[2] 4
+// w[3] 6
+// w[4] 8
+// c[0] 16
+// c[1] 24
+// c[2] 32
+//
+// total 40
+// E.
+struct P5 {
+ struct P3 a[2];
+ struct P2 t;
+};
+// Largest primitive is 8, so the local alignment value must be 8
+// |P3 10|P3 10|gap 4|P2 16|
+//
+// a[0] 0
+// a[1] 10
+// t 24
diff --git a/3/9_data_structures/45_rec.c b/3/9_data_structures/45_rec.c
new file mode 100644
index 0000000..f04ac0e
--- /dev/null
+++ b/3/9_data_structures/45_rec.c
@@ -0,0 +1,42 @@
+struct {
+ char *a;
+ short b;
+ double c;
+ char d;
+ float e;
+ char f;
+ long g;
+ int h;
+} rec;
+// A.
+// |char* 8|short 2|gap 6|double 8|char 1|float 4|char 1|gap 2|long 8|int 4|gap 4|
+// |-------|-------------|--------|---------------------------|------|-----------|
+// 8 8 8 8 8 8
+//
+// a 0
+// b 8
+// c 16
+// d 24
+// e 25
+// f 29
+// g 32
+// h 40
+//
+// B.
+// 48
+//
+// C.
+// |char* 8|short 2|char 1|float 4|char 1|double 8|long 8|int 4|gap 4|
+// |-------|-----------------------------|--------|------|-----------|
+// 8 8 8 8 8
+//
+// a 0
+// b 8
+// c 16
+// d 10
+// e 11
+// f 15
+// g 24
+// h 32
+//
+// total 40