From e8f93337949fc142df1766e1d652e0ed36e39a16 Mon Sep 17 00:00:00 2001 From: gwens Date: Fri, 14 Jul 2017 17:18:39 +0200 Subject: [PATCH] First commit --- 9781484224021.jpg | Bin 0 -> 20659 bytes Contributing.md | 14 + LICENSE.txt | 27 + README.md | 16 + assignments/1_io_library/stud/lib.inc | 61 +++ assignments/1_io_library/stud/test.py | 346 +++++++++++++ assignments/1_io_library/teacher/lib.inc | 190 +++++++ assignments/1_io_library/teacher/test.py | 346 +++++++++++++ assignments/2_dictionary/teacher/Makefile | 20 + assignments/2_dictionary/teacher/colon.inc | 10 + assignments/2_dictionary/teacher/dict.asm | 29 ++ assignments/2_dictionary/teacher/lib.asm | 216 ++++++++ assignments/2_dictionary/teacher/main.asm | 56 ++ assignments/2_dictionary/teacher/words.inc | 8 + assignments/forth-bootstrap/teacher/Makefile | 30 ++ .../forth-bootstrap/teacher/mwe/forth.asm | 80 +++ .../forth-bootstrap/teacher/mwe/lib.inc | 190 +++++++ .../forth-bootstrap/teacher/mwe/macro.asm | 33 ++ .../forth-bootstrap/teacher/src/forthress.asm | 49 ++ .../forth-bootstrap/teacher/src/macro.inc | 65 +++ .../forth-bootstrap/teacher/src/util.asm | 199 ++++++++ .../forth-bootstrap/teacher/src/util.inc | 17 + .../forth-bootstrap/teacher/src/words.inc | 482 ++++++++++++++++++ listings/appendix_gdb/call_stack/call_stack.c | 17 + .../appendix_gdb/print_rax_2/print_rax_2.asm | 32 ++ .../Makefile_simple/Makefile_simple | 11 + .../appendix_make/Makefile_vars/Makefile_vars | 17 + .../makefile_autovars/makefile_autovars | 16 + listings/chap10/file/file.h | 6 + listings/chap10/fun_decl_def/fun_decl_def.c | 7 + .../fun_mutual_recursive_bad.c | 7 + .../fun_proto_omit_arguments.c | 4 + listings/chap10/fun_sc_1/fun_sc_1.c | 5 + listings/chap10/fun_sc_2/fun_sc_2.c | 8 + listings/chap10/fun_sc_3/fun_sc_3.c | 3 + listings/chap10/glob_build/glob_build | 3 + listings/chap10/glob_nm/glob_nm | 12 + listings/chap10/ifdef_else_ex/ifdef_else_ex.c | 5 + listings/chap10/ifdef_ex/ifdef_ex.c | 3 + .../ifdef_pitfall_sig/ifdef_pitfall_sig.c | 7 + listings/chap10/ifndef_ex/ifndef_ex.c | 5 + .../inc_guard_motivation.c | 12 + .../incomplete_type_example.c | 5 + .../ldd_locating_libc/ldd_locating_libc | 5 + .../chap10/list_definition/list_definition.c | 4 + listings/chap10/main_ext/main_ext.c | 7 + listings/chap10/main_ldd/main_ldd.c | 7 + listings/chap10/main_printer/main_printer.c | 7 + .../main_printer_new/main_printer_new.c | 7 + listings/chap10/main_square/main_square | 18 + listings/chap10/main_square/main_square.c | 7 + .../multiple_inner_includes.c | 15 + .../mutually_recursive_structures.c | 10 + listings/chap10/pair/pair.h | 14 + listings/chap10/printer/printer.c | 8 + listings/chap10/printer/printer.h | 2 + .../printf_check_header/printf_check_header | 5 + .../chap10/printf_lib_entry/printf_lib_entry | 7 + listings/chap10/simple_malloc/simple_malloc.c | 17 + listings/chap10/square/square | 16 + listings/chap10/square/square.c | 2 + listings/chap10/square_ext/square_ext.c | 2 + .../chap10/static_example/static_example.c | 11 + .../static_loc_var_example.c | 12 + .../struct_mutual_recursive_bad.c | 6 + listings/chap10/sum_malloc/sum_malloc.c | 45 ++ listings/chap11/.c | 3 + .../chap11/complex_decl_1/complex_decl_1.c | 1 + listings/chap11/deref_ex/deref_ex.c | 3 + listings/chap11/file_example/file_example.c | 12 + listings/chap11/flex_array/flex_array.c | 17 + .../chap11/flex_array_def/flex_array_def.c | 4 + .../chap11/fun_ptr_example/fun_ptr_example.c | 6 + .../fun_ptr_example_typedef.c | 7 + listings/chap11/inttypes/inttypes.c | 10 + .../malloc_cast_explicit.c | 1 + .../chap11/malloc_no_cast/malloc_no_cast.c | 5 + listings/chap11/null_check/null_check.c | 6 + listings/chap11/pointers_ex/pointers_ex.c | 3 + listings/chap11/ptr_change_ex/ptr_change_ex.c | 5 + listings/chap11/ptr_diff_calc/ptr_diff_calc.c | 4 + listings/chap11/ptr_mult_decl/ptr_mult_decl.c | 1 + listings/chap11/ptrdiff_bug/ptrdiff_bug.c | 10 + listings/chap11/str_glob/str_glob.c | 2 + listings/chap11/str_intern/str_intern.c | 3 + .../chap11/str_lit_example/str_lit_example.c | 1 + .../chap11/str_lit_ptr_ex/str_lit_ptr_ex.c | 2 + listings/chap11/str_loc/str_loc.c | 3 + listings/chap11/str_malloc/str_malloc.c | 10 + .../string_literal_mut/string_literal_mut.c | 3 + listings/chap11/void_ptr_ex/void_ptr_ex.c | 5 + listings/chap12/align_str_ex1/align_str_ex1 | 4 + .../chap12/align_str_read/align_str_read.c | 6 + listings/chap12/alignas_ex/alignas_ex.c | 8 + listings/chap12/alignof_ex/alignof_ex.c | 8 + listings/chap12/grammar_nat_pm/grammar_nat_pm | 6 + .../grammar_nat_pm_mult/grammar_nat_pm_mult | 8 + .../chap12/grammar_naturals/grammar_naturals | 4 + .../grammar_naturals_nullterm | 5 + .../grammar_priorities/grammar_priorities | 5 + listings/chap12/imp/imp | 12 + listings/chap12/pack_2/pack_2.c | 6 + listings/chap12/pack_4/pack_4.c | 6 + listings/chap12/pragma_pack/pragma_pack.c | 6 + listings/chap12/ptr_analysis1/ptr_analysis1.c | 6 + listings/chap12/ptr_analysis2/ptr_analysis2.c | 8 + listings/chap12/rec_desc_nat/rec_desc_nat.c | 45 ++ listings/chap12/seq_points/seq_points.c | 2 + .../str_attribute_packed.c | 5 + listings/chap13/assert/assert.c | 6 + listings/chap13/bmp_struct/bmp_struct.c | 20 + listings/chap13/div_cb/div_cb.c | 21 + .../chap13/doxygen_example/doxygen_example.h | 30 ++ listings/chap13/dump_1/dump_1.c | 5 + listings/chap13/dump_2/dump_2.c | 8 + listings/chap13/enum_ex/enum_ex.c | 5 + .../chap13/err_switch_arr/err_switch_arr.c | 21 + listings/chap13/error_code/error_code.c | 9 + listings/chap13/file_open_sep/file_open_sep.c | 28 + .../goto_error_recover/goto_error_recover.c | 16 + .../chap13/image_rot_stub/image_rot_stub.c | 38 ++ listings/chap13/list_sum_bad/list_sum_bad.c | 10 + listings/chap13/mem/mem.h | 36 ++ listings/chap13/mem_debug/mem_debug.c | 23 + listings/chap13/mem_str/mem_str.c | 5 + listings/chap13/pixel/pixel.c | 3 + .../chap13/reenterability/reenterability.c | 9 + listings/chap13/stack/stack.c | 55 ++ listings/chap13/stack/stack.h | 27 + .../struct_private_ex/struct_private_ex.c | 5 + .../chap14/buffer_overrun/buffer_overrun.c | 11 + listings/chap14/epilogue/epilogue.asm | 3 + listings/chap14/epilogue_alt/epilogue_alt.asm | 2 + listings/chap14/gdb_printf/gdb_printf | 4 + listings/chap14/lma_bad/lma_bad.c | 3 + listings/chap14/lma_good/lma_good.c | 3 + listings/chap14/longjmp/longjmp.c | 12 + listings/chap14/longjmp_ub/longjmp_ub.c | 9 + listings/chap14/maximum/maximum.asm | 23 + listings/chap14/maximum/maximum.c | 11 + .../maximum_refined/maximum_refined.asm | 16 + listings/chap14/printf_n/printf_n.c | 8 + listings/chap14/printf_n_ex/printf_n_ex.c | 3 + listings/chap14/printf_vuln/printf_vuln.c | 7 + listings/chap14/prologue/prologue.asm | 5 + .../restrict-hack-dump/restrict-hack-dump | 5 + listings/chap14/restrict-hack/restrict-hack.c | 11 + .../restrict_hierarchy/restrict_hierarchy.c | 11 + .../chap14/restrict_motiv/restrict_motiv.c | 4 + .../chap14/restrict_motiv1/restrict_motiv1.c | 4 + .../restrict_motiv_dump.asm | 7 + .../restrict_motiv_dump1.asm | 6 + listings/chap14/rz/rz.asm | 12 + listings/chap14/rz/rz.c | 10 + .../chap14/setjmp_volatile/setjmp_volatile.c | 18 + .../chap14/strict-aliasing/strict-aliasing.c | 37 ++ listings/chap14/vararg/vararg.c | 18 + listings/chap14/volatile_ex/volatile_ex.asm | 29 ++ listings/chap14/volatile_ex/volatile_ex.c | 11 + .../volatile_setjmp_o0/volatile_setjmp_o0.asm | 51 ++ .../volatile_setjmp_o2/volatile_setjmp_o2.asm | 48 ++ listings/chap14/vsprintf/vsprintf.c | 16 + listings/chap15/.asm | 12 + listings/chap15/cm-example/cm-example.c | 17 + listings/chap15/da_crt1/da_crt1 | 18 + listings/chap15/da_crti/da_crti | 16 + listings/chap15/da_crtn/da_crtn | 14 + listings/chap15/dasm_init_fini/dasm_init_fini | 34 ++ listings/chap15/dynlib/dynlib.c | 7 + listings/chap15/ex1-lib/ex1-lib.asm | 16 + listings/chap15/ex1-main/ex1-main.asm | 13 + listings/chap15/ex1-makefile/ex1-makefile | 13 + listings/chap15/ex2-lib/ex2-lib.asm | 14 + listings/chap15/ex2-main/ex2-main.asm | 19 + listings/chap15/ex3-lib/ex3-lib.asm | 28 + listings/chap15/ex3-main/ex3-main.asm | 29 ++ listings/chap15/ex4-Makefile/ex4-Makefile | 18 + listings/chap15/ex4-lib/ex4-lib.asm | 20 + listings/chap15/ex4-main/ex4-main.c | 11 + listings/chap15/gcc_alias/da | 160 ++++++ listings/chap15/gcc_alias/gcc_alias.c | 23 + .../gcc_aliased_gain/gcc_aliased_gain.asm | 22 + .../chap15/got_plt_dump_ex/got_plt_dump_ex.c | 4 + .../ld_preload_effect/ld_preload_effect | 6 + listings/chap15/libfun/libfun | 35 ++ listings/chap15/mainlib/mainlib.c | 8 + listings/chap15/mc-small/mc-small | 11 + listings/chap15/plt_rw/plt_rw.asm | 35 ++ listings/chap15/plt_sketch/plt_sketch.asm | 21 + listings/chap15/prelib/prelib.c | 4 + .../preload_launcher/preload_launcher.c | 6 + listings/chap15/so_adapter/so_adapter.c | 9 + .../visibility_symbol/visibility_symbol.c | 3 + .../binsearch_prefetch_off | 25 + .../binsearch_prefetch_off_cachegrind | 22 + .../binsearch_prefetch_on | 25 + .../binsearch_prefetch_on_cachegrind | 22 + .../cache_bypass_intrinsics.c | 12 + .../cachegrind_matrix_bad | 21 + .../common_subexpression.asm | 12 + .../common_subexpression.c | 13 + .../constant_propagation.asm | 3 + .../constant_propagation.c | 6 + listings/chap16/cp_fact/cp_fact.asm | 10 + listings/chap16/cp_fact/cp_fact.c | 12 + .../cycle_nonpar_arith/cycle_nonpar_arith.asm | 14 + .../cycle_par_arith/cycle_par_arith.asm | 11 + .../chap16/execution_time/execution_time.c | 25 + .../factorial_nontailrec.c | 7 + .../factorial_tailrec/factorial_tailrec.asm | 8 + .../factorial_tailrec/factorial_tailrec.c | 9 + .../image_sepia_c_example.c | 38 ++ .../matrix_init_linear/matrix_init_linear.c | 13 + .../chap16/matrix_init_ra/matrix_init_ra.c | 13 + listings/chap16/nrvo/nrvo.c | 19 + listings/chap16/nrvo_off/nrvo_off.asm | 45 ++ listings/chap16/nrvo_on/nrvo_on.asm | 18 + .../prefetch_binsearch/prefetch_binsearch.c | 46 ++ listings/chap16/rwgroup_bad/rwgroup_bad.asm | 8 + listings/chap16/rwgroup_good/rwgroup_good.asm | 8 + listings/chap16/simd_asm/simd_asm.asm | 10 + listings/chap16/simd_main/simd_main.c | 14 + listings/chap16/stack_unwind/stack_unwind.asm | 26 + listings/chap16/stack_unwind/stack_unwind.c | 7 + .../tail_rec_example_list.asm | 10 + .../tail_rec_example_list.c | 26 + listings/chap17/cas_counter/cas_counter.c | 9 + listings/chap17/condvar_mwe/condvar_mwe.c | 47 ++ listings/chap17/deadlock_ex/deadlock_ex | 15 + listings/chap17/dist_fact_mp/dist_fact_mp.c | 60 +++ .../dist_fact_mp_simple/dist_fact_mp_simple.c | 41 ++ listings/chap17/dist_fact_sp/dist_fact_sp.c | 20 + .../ex_locality_asm1/ex_locality_asm1.asm | 12 + .../ex_locality_asm2/ex_locality_asm2.asm | 10 + .../chap17/ex_locality_src/ex_locality_src.c | 7 + listings/chap17/livelock_ex/livelock_ex | 21 + .../mem_reorder_sample/mem_reorder_sample | 13 + .../mem_reorder_sample/mem_reorder_sample.c | 12 + .../mem_reorder_sample_happened | 12 + .../mem_reorder_sample_happened.c | 12 + listings/chap17/mutex_ex1/mutex_ex1.c | 48 ++ .../mutex_ex_counter_bad.c | 25 + .../mutex_ex_counter_good.c | 35 ++ .../pthread_create_mwe/pthread_create_mwe.c | 20 + .../pthread_create_mwe_out | 21 + .../reordering_cpu_mwe/reordering_cpu_mwe.c | 76 +++ listings/chap17/semaphore_mwe/semaphore_mwe.c | 45 ++ .../chap17/thread_join_mwe/thread_join_mwe.c | 22 + listings/chap2/addressing/addressing.asm | 5 + listings/chap2/data_decl/data_decl.asm | 4 + listings/chap2/endianness/endianness.asm | 59 +++ listings/chap2/false/false.asm | 7 + listings/chap2/hello/hello.asm | 12 + .../hello_proper_exit/hello_proper_exit.asm | 17 + listings/chap2/jumps/jumps.asm | 10 + .../chap2/jumps_example/jumps_example.asm | 7 + listings/chap2/lea_vs_mov/lea_vs_mov.asm | 21 + listings/chap2/print_call/print_call.asm | 52 ++ listings/chap2/print_rax/print_rax.asm | 42 ++ listings/chap2/strlen/strlen.asm | 38 ++ listings/chap2/strlen_bug1/strlen_bug1.asm | 25 + listings/chap3/gdt64/gdt64.asm | 25 + .../chap3/loader_start32/loader_start32.asm | 23 + listings/chap3/risc_cisc/risc_cisc.asm | 10 + listings/chap4/mappings_loop/mappings_loop | 11 + .../chap4/mappings_loop/mappings_loop.asm | 7 + listings/chap4/mmap/mmap.asm | 66 +++ .../segfault_badaddr/segfault_badaddr.asm | 11 + .../segfault_readonly/segfault_readonly.asm | 14 + listings/chap5/cat_elfheader/cat_elfheader | 39 ++ .../define_cat_count/define_cat_count.asm | 4 + .../define_cat_count_preprocessed.asm | 4 + listings/chap5/defines/defines.asm | 16 + .../defines_preprocessed.asm | 14 + .../chap5/defining_in_cla/defining_in_cla.asm | 3 + listings/chap5/executable_object/a | Bin 0 -> 1208 bytes .../executable_object/executable_object.asm | 13 + listings/chap5/fib/fib.asm | 13 + .../chap5/hello_elfheader/hello_elfheader | 20 + listings/chap5/libso/Makefile | 18 + listings/chap5/libso/libso | 75 +++ listings/chap5/libso/libso.asm | 15 + listings/chap5/libso/main.asm | 12 + listings/chap5/libso_main/Makefile | 18 + listings/chap5/libso_main/libso_main.asm | 12 + .../chap5/linked_list_ex/linked_list_ex.asm | 15 + .../linked_list_ex_macro.asm | 12 + listings/chap5/macro_arg_types/e | Bin 0 -> 1112 bytes .../chap5/macro_arg_types/macro_arg_types.asm | 23 + .../macro_arg_types_preprocessed.asm | 19 + .../chap5/macro_asm_parts/macro_asm_parts.asm | 4 + .../macro_local_labels/macro_local_labels.asm | 10 + .../macro_local_labels_inst.asm | 15 + .../macro_simple_3arg/macro_simple_3arg.asm | 5 + .../macro_simple_3arg_inst.asm | 3 + listings/chap5/macroif/macroif.asm | 16 + .../macroif_preprocessed.asm | 6 + listings/chap5/nm/nm | 6 + listings/chap5/objdump_d/objdump_d | 21 + listings/chap5/objdump_tf/objdump_tf | 21 + listings/chap5/prime/prime.asm | 16 + .../prime_preprocessed/prime_preprocessed.asm | 19 + listings/chap5/pushr/pushr.asm | 10 + .../pushr_preprocessed/pushr_preprocessed.asm | 4 + listings/chap5/readelf_relocs/readelf_relocs | 7 + listings/chap5/rep/rep.asm | 8 + .../rep_preprocessed/rep_preprocessed.asm | 3 + listings/chap5/symbols/symbols | 18 + listings/chap5/symbols/symbols.asm | 20 + listings/chap5/symbols_maps/symbols_maps | 16 + listings/chap5/symbols_pht/symbols_pht | 20 + .../automaton_example_bits.asm | 43 ++ .../forth_colon_usage/forth_colon_usage.asm | 4 + .../forth_dict_example_macro.asm | 4 + .../forth_dict_example_nomacro.asm | 12 + .../forth_dict_sample/forth_dict_sample.asm | 33 ++ listings/chap7/forth_discr/forth_discr | 3 + listings/chap7/forth_docol/forth_docol.asm | 11 + .../forth_interpreter_end.asm | 2 + listings/chap7/forth_next/forth_next.asm | 5 + .../forth_program_stub/forth_program_stub.asm | 3 + listings/chap7/forth_sq/forth_sq | 1 + listings/chap7/itc/itc.asm | 112 ++++ .../native_overloading/native_overloading.asm | 3 + .../chap8/assignment_assoc/assignment_assoc.c | 2 + listings/chap8/block_example/block_example.c | 6 + .../chap8/block_variables/block_variables.c | 33 ++ listings/chap8/case_example/case_example.c | 14 + listings/chap8/case_magic/case_magic.c | 10 + listings/chap8/dangling_else/dangling_else.c | 13 + .../chap8/define_example1/define_example1.c | 1 + .../chap8/define_example2/define_example2.c | 1 + .../define_parentheses/define_parentheses.c | 3 + .../define_parentheses_preprocessed.c | 1 + listings/chap8/div_assoc/div_assoc.c | 2 + listings/chap8/divisor/divisor.c | 17 + .../chap8/do_while_example/do_while_example.c | 6 + listings/chap8/expr_example/expr_example.c | 4 + .../float_reinterpret/float_reinterpret.c | 6 + listings/chap8/for_example/for_example.c | 5 + .../chap8/function_example/function_example.c | 8 + listings/chap8/goto/goto.c | 10 + listings/chap8/hello/hello.c | 21 + listings/chap8/if_example/if_example.c | 12 + listings/chap8/if_no_braces/if_no_braces.c | 4 + listings/chap8/infinite_for/infinite_for.c | 4 + listings/chap8/is_fib/is_fib.c | 28 + listings/chap8/list_sum_bad/list_sum_bad.c | 9 + listings/chap8/logic_lazy/logic_lazy.c | 9 + listings/chap8/loop_cont/loop_cont.c | 5 + .../chap8/no_arguments_ex/no_arguments_ex.c | 1 + listings/chap8/proc_example/proc_example.c | 4 + .../chap8/rvalue_example/rvalue_example.c | 3 + listings/chap8/spacing_1/spacing_1.c | 5 + listings/chap8/spacing_2/spacing_2.c | 5 + listings/chap8/while_example/while_example.c | 5 + .../chap8/while_for_equiv/while_for_equiv.c | 13 + listings/chap9/anon_no/anon_no.c | 12 + listings/chap9/anon_struct/anon_struct.c | 10 + listings/chap9/array_decl/array_decl.c | 5 + .../chap9/array_example_rw/array_example_rw.c | 6 + .../chap9/array_param_size/array_param_size.c | 1 + .../array_param_size_static.c | 1 + listings/chap9/beg1/beg1.c | 11 + listings/chap9/beg2/beg2.c | 11 + listings/chap9/beg3/beg3.c | 16 + listings/chap9/beg4/beg4.c | 16 + listings/chap9/beg5/beg5.c | 15 + listings/chap9/beg6/beg6.c | 17 + listings/chap9/beg7/beg7.c | 16 + listings/chap9/beg8/beg8.c | 20 + listings/chap9/beg9/beg9.c | 19 + listings/chap9/c_inclusion/c_inclusion.c | 23 + listings/chap9/c_overload_11/c_overload_11.c | 16 + .../c_parametric_polymorphism.c | 25 + listings/chap9/char_example/char_example.c | 3 + listings/chap9/const_cast/const_cast.c | 9 + listings/chap9/const_def/const_def.c | 16 + listings/chap9/const_discard/const_discard.c | 8 + .../designated_initializers_arrays.c | 16 + listings/chap9/enum_example/enum_example.c | 11 + listings/chap9/fun_array1/fun_array1.c | 4 + listings/chap9/fun_array2/fun_array2.c | 4 + listings/chap9/fun_array3/fun_array3.c | 4 + listings/chap9/fun_ptr_diff/fun_ptr_diff.c | 27 + .../chap9/fun_type_example/fun_type_example.c | 12 + .../fun_type_example_alt.c | 12 + .../chap9/fun_types_decl/fun_types_decl.c | 9 + .../chap9/int_float_conv/int_float_conv.c | 3 + .../int_promotion_pitfall.c | 14 + listings/chap9/macro_concat/macro_concat.c | 7 + .../macro_define_pair/macro_define_pair.c | 7 + listings/chap9/macro_str/macro_str.c | 4 + .../chap9/main_revisited/main_revisited.c | 8 + listings/chap9/pixel/pixel.c | 6 + listings/chap9/ptr_deref/ptr_deref.c | 6 + .../size_int_difference/size_int_difference.c | 6 + listings/chap9/sizeof_array/sizeof_array.c | 9 + .../chap9/sizeof_array_fun/sizeof_array_fun.c | 9 + .../string_literal_breaks.c | 2 + listings/chap9/struct_anon/struct_anon.c | 3 + .../chap9/struct_c99_init/struct_c99_init.c | 6 + listings/chap9/struct_init/struct_init.c | 3 + listings/chap9/struct_named/struct_named.c | 10 + .../chap9/struct_namespace/struct_namespace.c | 10 + listings/chap9/struct_zero/struct_zero.c | 4 + listings/chap9/type_cast/type_cast.c | 6 + .../typedef_bad_fun_ptr/typedef_bad_fun_ptr.c | 1 + .../chap9/typedef_example/typedef_example.c | 1 + .../typedef_good_fun_ptr.c | 5 + .../typedef_struct_simple.c | 1 + listings/chap9/union_example/union_example.c | 8 + .../chap9/union_guarantee/union_guarantee.c | 16 + listings/chap9/void_deref/void_deref.c | 4 + listings/start_tests.sh | 14 + listings/tests/strlen.asm/strlen.asm | Bin 0 -> 1024 bytes listings/tests_asm | 1 + 417 files changed, 7879 insertions(+) create mode 100644 9781484224021.jpg create mode 100755 Contributing.md create mode 100755 LICENSE.txt create mode 100755 README.md create mode 100755 assignments/1_io_library/stud/lib.inc create mode 100755 assignments/1_io_library/stud/test.py create mode 100755 assignments/1_io_library/teacher/lib.inc create mode 100755 assignments/1_io_library/teacher/test.py create mode 100755 assignments/2_dictionary/teacher/Makefile create mode 100755 assignments/2_dictionary/teacher/colon.inc create mode 100755 assignments/2_dictionary/teacher/dict.asm create mode 100755 assignments/2_dictionary/teacher/lib.asm create mode 100755 assignments/2_dictionary/teacher/main.asm create mode 100755 assignments/2_dictionary/teacher/words.inc create mode 100755 assignments/forth-bootstrap/teacher/Makefile create mode 100755 assignments/forth-bootstrap/teacher/mwe/forth.asm create mode 100755 assignments/forth-bootstrap/teacher/mwe/lib.inc create mode 100755 assignments/forth-bootstrap/teacher/mwe/macro.asm create mode 100755 assignments/forth-bootstrap/teacher/src/forthress.asm create mode 100755 assignments/forth-bootstrap/teacher/src/macro.inc create mode 100755 assignments/forth-bootstrap/teacher/src/util.asm create mode 100755 assignments/forth-bootstrap/teacher/src/util.inc create mode 100755 assignments/forth-bootstrap/teacher/src/words.inc create mode 100755 listings/appendix_gdb/call_stack/call_stack.c create mode 100755 listings/appendix_gdb/print_rax_2/print_rax_2.asm create mode 100755 listings/appendix_make/Makefile_simple/Makefile_simple create mode 100755 listings/appendix_make/Makefile_vars/Makefile_vars create mode 100755 listings/appendix_make/makefile_autovars/makefile_autovars create mode 100755 listings/chap10/file/file.h create mode 100755 listings/chap10/fun_decl_def/fun_decl_def.c create mode 100755 listings/chap10/fun_mutual_recursive_bad/fun_mutual_recursive_bad.c create mode 100755 listings/chap10/fun_proto_omit_arguments/fun_proto_omit_arguments.c create mode 100755 listings/chap10/fun_sc_1/fun_sc_1.c create mode 100755 listings/chap10/fun_sc_2/fun_sc_2.c create mode 100755 listings/chap10/fun_sc_3/fun_sc_3.c create mode 100755 listings/chap10/glob_build/glob_build create mode 100755 listings/chap10/glob_nm/glob_nm create mode 100755 listings/chap10/ifdef_else_ex/ifdef_else_ex.c create mode 100755 listings/chap10/ifdef_ex/ifdef_ex.c create mode 100755 listings/chap10/ifdef_pitfall_sig/ifdef_pitfall_sig.c create mode 100755 listings/chap10/ifndef_ex/ifndef_ex.c create mode 100755 listings/chap10/inc_guard_motivation/inc_guard_motivation.c create mode 100755 listings/chap10/incomplete_type_example/incomplete_type_example.c create mode 100755 listings/chap10/ldd_locating_libc/ldd_locating_libc create mode 100755 listings/chap10/list_definition/list_definition.c create mode 100755 listings/chap10/main_ext/main_ext.c create mode 100755 listings/chap10/main_ldd/main_ldd.c create mode 100755 listings/chap10/main_printer/main_printer.c create mode 100755 listings/chap10/main_printer_new/main_printer_new.c create mode 100755 listings/chap10/main_square/main_square create mode 100755 listings/chap10/main_square/main_square.c create mode 100755 listings/chap10/multiple_inner_includes/multiple_inner_includes.c create mode 100755 listings/chap10/mutually_recursive_structures/mutually_recursive_structures.c create mode 100755 listings/chap10/pair/pair.h create mode 100755 listings/chap10/printer/printer.c create mode 100755 listings/chap10/printer/printer.h create mode 100755 listings/chap10/printf_check_header/printf_check_header create mode 100755 listings/chap10/printf_lib_entry/printf_lib_entry create mode 100755 listings/chap10/simple_malloc/simple_malloc.c create mode 100755 listings/chap10/square/square create mode 100755 listings/chap10/square/square.c create mode 100755 listings/chap10/square_ext/square_ext.c create mode 100755 listings/chap10/static_example/static_example.c create mode 100755 listings/chap10/static_loc_var_example/static_loc_var_example.c create mode 100755 listings/chap10/struct_mutual_recursive_bad/struct_mutual_recursive_bad.c create mode 100755 listings/chap10/sum_malloc/sum_malloc.c create mode 100755 listings/chap11/.c create mode 100755 listings/chap11/complex_decl_1/complex_decl_1.c create mode 100755 listings/chap11/deref_ex/deref_ex.c create mode 100755 listings/chap11/file_example/file_example.c create mode 100755 listings/chap11/flex_array/flex_array.c create mode 100755 listings/chap11/flex_array_def/flex_array_def.c create mode 100755 listings/chap11/fun_ptr_example/fun_ptr_example.c create mode 100755 listings/chap11/fun_ptr_example_typedef/fun_ptr_example_typedef.c create mode 100755 listings/chap11/inttypes/inttypes.c create mode 100755 listings/chap11/malloc_cast_explicit/malloc_cast_explicit.c create mode 100755 listings/chap11/malloc_no_cast/malloc_no_cast.c create mode 100755 listings/chap11/null_check/null_check.c create mode 100755 listings/chap11/pointers_ex/pointers_ex.c create mode 100755 listings/chap11/ptr_change_ex/ptr_change_ex.c create mode 100755 listings/chap11/ptr_diff_calc/ptr_diff_calc.c create mode 100755 listings/chap11/ptr_mult_decl/ptr_mult_decl.c create mode 100755 listings/chap11/ptrdiff_bug/ptrdiff_bug.c create mode 100755 listings/chap11/str_glob/str_glob.c create mode 100755 listings/chap11/str_intern/str_intern.c create mode 100755 listings/chap11/str_lit_example/str_lit_example.c create mode 100755 listings/chap11/str_lit_ptr_ex/str_lit_ptr_ex.c create mode 100755 listings/chap11/str_loc/str_loc.c create mode 100755 listings/chap11/str_malloc/str_malloc.c create mode 100755 listings/chap11/string_literal_mut/string_literal_mut.c create mode 100755 listings/chap11/void_ptr_ex/void_ptr_ex.c create mode 100755 listings/chap12/align_str_ex1/align_str_ex1 create mode 100755 listings/chap12/align_str_read/align_str_read.c create mode 100755 listings/chap12/alignas_ex/alignas_ex.c create mode 100755 listings/chap12/alignof_ex/alignof_ex.c create mode 100755 listings/chap12/grammar_nat_pm/grammar_nat_pm create mode 100755 listings/chap12/grammar_nat_pm_mult/grammar_nat_pm_mult create mode 100755 listings/chap12/grammar_naturals/grammar_naturals create mode 100755 listings/chap12/grammar_naturals_nullterm/grammar_naturals_nullterm create mode 100755 listings/chap12/grammar_priorities/grammar_priorities create mode 100755 listings/chap12/imp/imp create mode 100755 listings/chap12/pack_2/pack_2.c create mode 100755 listings/chap12/pack_4/pack_4.c create mode 100755 listings/chap12/pragma_pack/pragma_pack.c create mode 100755 listings/chap12/ptr_analysis1/ptr_analysis1.c create mode 100755 listings/chap12/ptr_analysis2/ptr_analysis2.c create mode 100755 listings/chap12/rec_desc_nat/rec_desc_nat.c create mode 100755 listings/chap12/seq_points/seq_points.c create mode 100755 listings/chap12/str_attribute_packed/str_attribute_packed.c create mode 100755 listings/chap13/assert/assert.c create mode 100755 listings/chap13/bmp_struct/bmp_struct.c create mode 100755 listings/chap13/div_cb/div_cb.c create mode 100755 listings/chap13/doxygen_example/doxygen_example.h create mode 100755 listings/chap13/dump_1/dump_1.c create mode 100755 listings/chap13/dump_2/dump_2.c create mode 100755 listings/chap13/enum_ex/enum_ex.c create mode 100755 listings/chap13/err_switch_arr/err_switch_arr.c create mode 100755 listings/chap13/error_code/error_code.c create mode 100755 listings/chap13/file_open_sep/file_open_sep.c create mode 100755 listings/chap13/goto_error_recover/goto_error_recover.c create mode 100755 listings/chap13/image_rot_stub/image_rot_stub.c create mode 100755 listings/chap13/list_sum_bad/list_sum_bad.c create mode 100755 listings/chap13/mem/mem.h create mode 100755 listings/chap13/mem_debug/mem_debug.c create mode 100755 listings/chap13/mem_str/mem_str.c create mode 100755 listings/chap13/pixel/pixel.c create mode 100755 listings/chap13/reenterability/reenterability.c create mode 100755 listings/chap13/stack/stack.c create mode 100755 listings/chap13/stack/stack.h create mode 100755 listings/chap13/struct_private_ex/struct_private_ex.c create mode 100755 listings/chap14/buffer_overrun/buffer_overrun.c create mode 100755 listings/chap14/epilogue/epilogue.asm create mode 100755 listings/chap14/epilogue_alt/epilogue_alt.asm create mode 100755 listings/chap14/gdb_printf/gdb_printf create mode 100755 listings/chap14/lma_bad/lma_bad.c create mode 100755 listings/chap14/lma_good/lma_good.c create mode 100755 listings/chap14/longjmp/longjmp.c create mode 100755 listings/chap14/longjmp_ub/longjmp_ub.c create mode 100755 listings/chap14/maximum/maximum.asm create mode 100755 listings/chap14/maximum/maximum.c create mode 100755 listings/chap14/maximum_refined/maximum_refined.asm create mode 100755 listings/chap14/printf_n/printf_n.c create mode 100755 listings/chap14/printf_n_ex/printf_n_ex.c create mode 100755 listings/chap14/printf_vuln/printf_vuln.c create mode 100755 listings/chap14/prologue/prologue.asm create mode 100755 listings/chap14/restrict-hack-dump/restrict-hack-dump create mode 100755 listings/chap14/restrict-hack/restrict-hack.c create mode 100755 listings/chap14/restrict_hierarchy/restrict_hierarchy.c create mode 100755 listings/chap14/restrict_motiv/restrict_motiv.c create mode 100755 listings/chap14/restrict_motiv1/restrict_motiv1.c create mode 100755 listings/chap14/restrict_motiv_dump/restrict_motiv_dump.asm create mode 100755 listings/chap14/restrict_motiv_dump1/restrict_motiv_dump1.asm create mode 100755 listings/chap14/rz/rz.asm create mode 100755 listings/chap14/rz/rz.c create mode 100755 listings/chap14/setjmp_volatile/setjmp_volatile.c create mode 100755 listings/chap14/strict-aliasing/strict-aliasing.c create mode 100755 listings/chap14/vararg/vararg.c create mode 100755 listings/chap14/volatile_ex/volatile_ex.asm create mode 100755 listings/chap14/volatile_ex/volatile_ex.c create mode 100755 listings/chap14/volatile_setjmp_o0/volatile_setjmp_o0.asm create mode 100755 listings/chap14/volatile_setjmp_o2/volatile_setjmp_o2.asm create mode 100755 listings/chap14/vsprintf/vsprintf.c create mode 100755 listings/chap15/.asm create mode 100755 listings/chap15/cm-example/cm-example.c create mode 100755 listings/chap15/da_crt1/da_crt1 create mode 100755 listings/chap15/da_crti/da_crti create mode 100755 listings/chap15/da_crtn/da_crtn create mode 100755 listings/chap15/dasm_init_fini/dasm_init_fini create mode 100755 listings/chap15/dynlib/dynlib.c create mode 100755 listings/chap15/ex1-lib/ex1-lib.asm create mode 100755 listings/chap15/ex1-main/ex1-main.asm create mode 100755 listings/chap15/ex1-makefile/ex1-makefile create mode 100755 listings/chap15/ex2-lib/ex2-lib.asm create mode 100755 listings/chap15/ex2-main/ex2-main.asm create mode 100755 listings/chap15/ex3-lib/ex3-lib.asm create mode 100755 listings/chap15/ex3-main/ex3-main.asm create mode 100755 listings/chap15/ex4-Makefile/ex4-Makefile create mode 100755 listings/chap15/ex4-lib/ex4-lib.asm create mode 100755 listings/chap15/ex4-main/ex4-main.c create mode 100755 listings/chap15/gcc_alias/da create mode 100755 listings/chap15/gcc_alias/gcc_alias.c create mode 100755 listings/chap15/gcc_aliased_gain/gcc_aliased_gain.asm create mode 100755 listings/chap15/got_plt_dump_ex/got_plt_dump_ex.c create mode 100755 listings/chap15/ld_preload_effect/ld_preload_effect create mode 100755 listings/chap15/libfun/libfun create mode 100755 listings/chap15/mainlib/mainlib.c create mode 100755 listings/chap15/mc-small/mc-small create mode 100755 listings/chap15/plt_rw/plt_rw.asm create mode 100755 listings/chap15/plt_sketch/plt_sketch.asm create mode 100755 listings/chap15/prelib/prelib.c create mode 100755 listings/chap15/preload_launcher/preload_launcher.c create mode 100755 listings/chap15/so_adapter/so_adapter.c create mode 100755 listings/chap15/visibility_symbol/visibility_symbol.c create mode 100755 listings/chap16/binsearch_prefetch_off/binsearch_prefetch_off create mode 100755 listings/chap16/binsearch_prefetch_off_cachegrind/binsearch_prefetch_off_cachegrind create mode 100755 listings/chap16/binsearch_prefetch_on/binsearch_prefetch_on create mode 100755 listings/chap16/binsearch_prefetch_on_cachegrind/binsearch_prefetch_on_cachegrind create mode 100755 listings/chap16/cache_bypass_intrinsics/cache_bypass_intrinsics.c create mode 100755 listings/chap16/cachegrind_matrix_bad/cachegrind_matrix_bad create mode 100755 listings/chap16/common_subexpression/common_subexpression.asm create mode 100755 listings/chap16/common_subexpression/common_subexpression.c create mode 100755 listings/chap16/constant_propagation/constant_propagation.asm create mode 100755 listings/chap16/constant_propagation/constant_propagation.c create mode 100755 listings/chap16/cp_fact/cp_fact.asm create mode 100755 listings/chap16/cp_fact/cp_fact.c create mode 100755 listings/chap16/cycle_nonpar_arith/cycle_nonpar_arith.asm create mode 100755 listings/chap16/cycle_par_arith/cycle_par_arith.asm create mode 100755 listings/chap16/execution_time/execution_time.c create mode 100755 listings/chap16/factorial_nontailrec/factorial_nontailrec.c create mode 100755 listings/chap16/factorial_tailrec/factorial_tailrec.asm create mode 100755 listings/chap16/factorial_tailrec/factorial_tailrec.c create mode 100755 listings/chap16/image_sepia_c_example/image_sepia_c_example.c create mode 100755 listings/chap16/matrix_init_linear/matrix_init_linear.c create mode 100755 listings/chap16/matrix_init_ra/matrix_init_ra.c create mode 100755 listings/chap16/nrvo/nrvo.c create mode 100755 listings/chap16/nrvo_off/nrvo_off.asm create mode 100755 listings/chap16/nrvo_on/nrvo_on.asm create mode 100755 listings/chap16/prefetch_binsearch/prefetch_binsearch.c create mode 100755 listings/chap16/rwgroup_bad/rwgroup_bad.asm create mode 100755 listings/chap16/rwgroup_good/rwgroup_good.asm create mode 100755 listings/chap16/simd_asm/simd_asm.asm create mode 100755 listings/chap16/simd_main/simd_main.c create mode 100755 listings/chap16/stack_unwind/stack_unwind.asm create mode 100755 listings/chap16/stack_unwind/stack_unwind.c create mode 100755 listings/chap16/tail_rec_example_list/tail_rec_example_list.asm create mode 100755 listings/chap16/tail_rec_example_list/tail_rec_example_list.c create mode 100755 listings/chap17/cas_counter/cas_counter.c create mode 100755 listings/chap17/condvar_mwe/condvar_mwe.c create mode 100755 listings/chap17/deadlock_ex/deadlock_ex create mode 100755 listings/chap17/dist_fact_mp/dist_fact_mp.c create mode 100755 listings/chap17/dist_fact_mp_simple/dist_fact_mp_simple.c create mode 100755 listings/chap17/dist_fact_sp/dist_fact_sp.c create mode 100755 listings/chap17/ex_locality_asm1/ex_locality_asm1.asm create mode 100755 listings/chap17/ex_locality_asm2/ex_locality_asm2.asm create mode 100755 listings/chap17/ex_locality_src/ex_locality_src.c create mode 100755 listings/chap17/livelock_ex/livelock_ex create mode 100755 listings/chap17/mem_reorder_sample/mem_reorder_sample create mode 100755 listings/chap17/mem_reorder_sample/mem_reorder_sample.c create mode 100755 listings/chap17/mem_reorder_sample_happened/mem_reorder_sample_happened create mode 100755 listings/chap17/mem_reorder_sample_happened/mem_reorder_sample_happened.c create mode 100755 listings/chap17/mutex_ex1/mutex_ex1.c create mode 100755 listings/chap17/mutex_ex_counter_bad/mutex_ex_counter_bad.c create mode 100755 listings/chap17/mutex_ex_counter_good/mutex_ex_counter_good.c create mode 100755 listings/chap17/pthread_create_mwe/pthread_create_mwe.c create mode 100755 listings/chap17/pthread_create_mwe_out/pthread_create_mwe_out create mode 100755 listings/chap17/reordering_cpu_mwe/reordering_cpu_mwe.c create mode 100755 listings/chap17/semaphore_mwe/semaphore_mwe.c create mode 100755 listings/chap17/thread_join_mwe/thread_join_mwe.c create mode 100755 listings/chap2/addressing/addressing.asm create mode 100755 listings/chap2/data_decl/data_decl.asm create mode 100755 listings/chap2/endianness/endianness.asm create mode 100755 listings/chap2/false/false.asm create mode 100755 listings/chap2/hello/hello.asm create mode 100755 listings/chap2/hello_proper_exit/hello_proper_exit.asm create mode 100755 listings/chap2/jumps/jumps.asm create mode 100755 listings/chap2/jumps_example/jumps_example.asm create mode 100755 listings/chap2/lea_vs_mov/lea_vs_mov.asm create mode 100755 listings/chap2/print_call/print_call.asm create mode 100755 listings/chap2/print_rax/print_rax.asm create mode 100755 listings/chap2/strlen/strlen.asm create mode 100755 listings/chap2/strlen_bug1/strlen_bug1.asm create mode 100755 listings/chap3/gdt64/gdt64.asm create mode 100755 listings/chap3/loader_start32/loader_start32.asm create mode 100755 listings/chap3/risc_cisc/risc_cisc.asm create mode 100755 listings/chap4/mappings_loop/mappings_loop create mode 100755 listings/chap4/mappings_loop/mappings_loop.asm create mode 100755 listings/chap4/mmap/mmap.asm create mode 100755 listings/chap4/segfault_badaddr/segfault_badaddr.asm create mode 100755 listings/chap4/segfault_readonly/segfault_readonly.asm create mode 100755 listings/chap5/cat_elfheader/cat_elfheader create mode 100755 listings/chap5/define_cat_count/define_cat_count.asm create mode 100755 listings/chap5/define_cat_count_preprocessed/define_cat_count_preprocessed.asm create mode 100755 listings/chap5/defines/defines.asm create mode 100755 listings/chap5/defines_preprocessed/defines_preprocessed.asm create mode 100755 listings/chap5/defining_in_cla/defining_in_cla.asm create mode 100755 listings/chap5/executable_object/a create mode 100755 listings/chap5/executable_object/executable_object.asm create mode 100755 listings/chap5/fib/fib.asm create mode 100755 listings/chap5/hello_elfheader/hello_elfheader create mode 100755 listings/chap5/libso/Makefile create mode 100755 listings/chap5/libso/libso create mode 100755 listings/chap5/libso/libso.asm create mode 100755 listings/chap5/libso/main.asm create mode 100755 listings/chap5/libso_main/Makefile create mode 100755 listings/chap5/libso_main/libso_main.asm create mode 100755 listings/chap5/linked_list_ex/linked_list_ex.asm create mode 100755 listings/chap5/linked_list_ex_macro/linked_list_ex_macro.asm create mode 100755 listings/chap5/macro_arg_types/e create mode 100755 listings/chap5/macro_arg_types/macro_arg_types.asm create mode 100755 listings/chap5/macro_arg_types_preprocessed/macro_arg_types_preprocessed.asm create mode 100755 listings/chap5/macro_asm_parts/macro_asm_parts.asm create mode 100755 listings/chap5/macro_local_labels/macro_local_labels.asm create mode 100755 listings/chap5/macro_local_labels_inst/macro_local_labels_inst.asm create mode 100755 listings/chap5/macro_simple_3arg/macro_simple_3arg.asm create mode 100755 listings/chap5/macro_simple_3arg_inst/macro_simple_3arg_inst.asm create mode 100755 listings/chap5/macroif/macroif.asm create mode 100755 listings/chap5/macroif_preprocessed/macroif_preprocessed.asm create mode 100755 listings/chap5/nm/nm create mode 100755 listings/chap5/objdump_d/objdump_d create mode 100755 listings/chap5/objdump_tf/objdump_tf create mode 100755 listings/chap5/prime/prime.asm create mode 100755 listings/chap5/prime_preprocessed/prime_preprocessed.asm create mode 100755 listings/chap5/pushr/pushr.asm create mode 100755 listings/chap5/pushr_preprocessed/pushr_preprocessed.asm create mode 100755 listings/chap5/readelf_relocs/readelf_relocs create mode 100755 listings/chap5/rep/rep.asm create mode 100755 listings/chap5/rep_preprocessed/rep_preprocessed.asm create mode 100755 listings/chap5/symbols/symbols create mode 100755 listings/chap5/symbols/symbols.asm create mode 100755 listings/chap5/symbols_maps/symbols_maps create mode 100755 listings/chap5/symbols_pht/symbols_pht create mode 100755 listings/chap7/automaton_example_bits/automaton_example_bits.asm create mode 100755 listings/chap7/forth_colon_usage/forth_colon_usage.asm create mode 100755 listings/chap7/forth_dict_example_macro/forth_dict_example_macro.asm create mode 100755 listings/chap7/forth_dict_example_nomacro/forth_dict_example_nomacro.asm create mode 100755 listings/chap7/forth_dict_sample/forth_dict_sample.asm create mode 100755 listings/chap7/forth_discr/forth_discr create mode 100755 listings/chap7/forth_docol/forth_docol.asm create mode 100755 listings/chap7/forth_interpreter_end/forth_interpreter_end.asm create mode 100755 listings/chap7/forth_next/forth_next.asm create mode 100755 listings/chap7/forth_program_stub/forth_program_stub.asm create mode 100755 listings/chap7/forth_sq/forth_sq create mode 100755 listings/chap7/itc/itc.asm create mode 100755 listings/chap7/native_overloading/native_overloading.asm create mode 100755 listings/chap8/assignment_assoc/assignment_assoc.c create mode 100755 listings/chap8/block_example/block_example.c create mode 100755 listings/chap8/block_variables/block_variables.c create mode 100755 listings/chap8/case_example/case_example.c create mode 100755 listings/chap8/case_magic/case_magic.c create mode 100755 listings/chap8/dangling_else/dangling_else.c create mode 100755 listings/chap8/define_example1/define_example1.c create mode 100755 listings/chap8/define_example2/define_example2.c create mode 100755 listings/chap8/define_parentheses/define_parentheses.c create mode 100755 listings/chap8/define_parentheses_preprocessed/define_parentheses_preprocessed.c create mode 100755 listings/chap8/div_assoc/div_assoc.c create mode 100755 listings/chap8/divisor/divisor.c create mode 100755 listings/chap8/do_while_example/do_while_example.c create mode 100755 listings/chap8/expr_example/expr_example.c create mode 100755 listings/chap8/float_reinterpret/float_reinterpret.c create mode 100755 listings/chap8/for_example/for_example.c create mode 100755 listings/chap8/function_example/function_example.c create mode 100755 listings/chap8/goto/goto.c create mode 100755 listings/chap8/hello/hello.c create mode 100755 listings/chap8/if_example/if_example.c create mode 100755 listings/chap8/if_no_braces/if_no_braces.c create mode 100755 listings/chap8/infinite_for/infinite_for.c create mode 100755 listings/chap8/is_fib/is_fib.c create mode 100755 listings/chap8/list_sum_bad/list_sum_bad.c create mode 100755 listings/chap8/logic_lazy/logic_lazy.c create mode 100755 listings/chap8/loop_cont/loop_cont.c create mode 100755 listings/chap8/no_arguments_ex/no_arguments_ex.c create mode 100755 listings/chap8/proc_example/proc_example.c create mode 100755 listings/chap8/rvalue_example/rvalue_example.c create mode 100755 listings/chap8/spacing_1/spacing_1.c create mode 100755 listings/chap8/spacing_2/spacing_2.c create mode 100755 listings/chap8/while_example/while_example.c create mode 100755 listings/chap8/while_for_equiv/while_for_equiv.c create mode 100755 listings/chap9/anon_no/anon_no.c create mode 100755 listings/chap9/anon_struct/anon_struct.c create mode 100755 listings/chap9/array_decl/array_decl.c create mode 100755 listings/chap9/array_example_rw/array_example_rw.c create mode 100755 listings/chap9/array_param_size/array_param_size.c create mode 100755 listings/chap9/array_param_size_static/array_param_size_static.c create mode 100755 listings/chap9/beg1/beg1.c create mode 100755 listings/chap9/beg2/beg2.c create mode 100755 listings/chap9/beg3/beg3.c create mode 100755 listings/chap9/beg4/beg4.c create mode 100755 listings/chap9/beg5/beg5.c create mode 100755 listings/chap9/beg6/beg6.c create mode 100755 listings/chap9/beg7/beg7.c create mode 100755 listings/chap9/beg8/beg8.c create mode 100755 listings/chap9/beg9/beg9.c create mode 100755 listings/chap9/c_inclusion/c_inclusion.c create mode 100755 listings/chap9/c_overload_11/c_overload_11.c create mode 100755 listings/chap9/c_parametric_polymorphism/c_parametric_polymorphism.c create mode 100755 listings/chap9/char_example/char_example.c create mode 100755 listings/chap9/const_cast/const_cast.c create mode 100755 listings/chap9/const_def/const_def.c create mode 100755 listings/chap9/const_discard/const_discard.c create mode 100755 listings/chap9/designated_initializers_arrays/designated_initializers_arrays.c create mode 100755 listings/chap9/enum_example/enum_example.c create mode 100755 listings/chap9/fun_array1/fun_array1.c create mode 100755 listings/chap9/fun_array2/fun_array2.c create mode 100755 listings/chap9/fun_array3/fun_array3.c create mode 100755 listings/chap9/fun_ptr_diff/fun_ptr_diff.c create mode 100755 listings/chap9/fun_type_example/fun_type_example.c create mode 100755 listings/chap9/fun_type_example_alt/fun_type_example_alt.c create mode 100755 listings/chap9/fun_types_decl/fun_types_decl.c create mode 100755 listings/chap9/int_float_conv/int_float_conv.c create mode 100755 listings/chap9/int_promotion_pitfall/int_promotion_pitfall.c create mode 100755 listings/chap9/macro_concat/macro_concat.c create mode 100755 listings/chap9/macro_define_pair/macro_define_pair.c create mode 100755 listings/chap9/macro_str/macro_str.c create mode 100755 listings/chap9/main_revisited/main_revisited.c create mode 100755 listings/chap9/pixel/pixel.c create mode 100755 listings/chap9/ptr_deref/ptr_deref.c create mode 100755 listings/chap9/size_int_difference/size_int_difference.c create mode 100755 listings/chap9/sizeof_array/sizeof_array.c create mode 100755 listings/chap9/sizeof_array_fun/sizeof_array_fun.c create mode 100755 listings/chap9/string_literal_breaks/string_literal_breaks.c create mode 100755 listings/chap9/struct_anon/struct_anon.c create mode 100755 listings/chap9/struct_c99_init/struct_c99_init.c create mode 100755 listings/chap9/struct_init/struct_init.c create mode 100755 listings/chap9/struct_named/struct_named.c create mode 100755 listings/chap9/struct_namespace/struct_namespace.c create mode 100755 listings/chap9/struct_zero/struct_zero.c create mode 100755 listings/chap9/type_cast/type_cast.c create mode 100755 listings/chap9/typedef_bad_fun_ptr/typedef_bad_fun_ptr.c create mode 100755 listings/chap9/typedef_example/typedef_example.c create mode 100755 listings/chap9/typedef_good_fun_ptr/typedef_good_fun_ptr.c create mode 100755 listings/chap9/typedef_struct_simple/typedef_struct_simple.c create mode 100755 listings/chap9/union_example/union_example.c create mode 100755 listings/chap9/union_guarantee/union_guarantee.c create mode 100755 listings/chap9/void_deref/void_deref.c create mode 100755 listings/start_tests.sh create mode 100755 listings/tests/strlen.asm/strlen.asm create mode 100755 listings/tests_asm diff --git a/9781484224021.jpg b/9781484224021.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a021513aee5ceda1efcecfa676b062b0ea1032c4 GIT binary patch literal 20659 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 ReH%tX1DMA=&n=Wb^Di{WeUtzI literal 0 HcmV?d00001 diff --git a/Contributing.md b/Contributing.md new file mode 100755 index 0000000..905ff61 --- /dev/null +++ b/Contributing.md @@ -0,0 +1,14 @@ +# Contributing to Apress Source Code + +Copyright for Apress source code belongs to the author(s). However, under fair use you are encouraged to fork and contribute minor corrections and updates for the benefit of the author(s) and other readers. + +## How to Contribute + +1. Make sure you have a GitHub account. +2. Fork the repository for the relevant book. +3. Create a new branch on which to make your change, e.g. +`git checkout -b my_code_contribution` +4. Commit your change. Include a commit message describing the correction. Please note that if your commit message is not clear, the correction will not be accepted. +5. Submit a pull request. + +Thank you for your contribution! \ No newline at end of file diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100755 index 0000000..0cd492d --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,27 @@ +Freeware License, some rights reserved + +Copyright (c) 2017 Igor Zhirkov + +Permission is hereby granted, free of charge, to anyone obtaining a copy +of this software and associated documentation files (the "Software"), +to work with the Software within the limits of freeware distribution and fair use. +This includes the rights to use, copy, and modify the Software for personal use. +Users are also allowed and encouraged to submit corrections and modifications +to the Software for the benefit of other users. + +It is not allowed to reuse, modify, or redistribute the Software for +commercial use in any way, or for a user’s educational materials such as books +or blog articles without prior permission from the copyright holder. + +The above copyright notice and this permission notice need to be included +in all copies or substantial portions of the software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS OR APRESS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + diff --git a/README.md b/README.md new file mode 100755 index 0000000..c22d73f --- /dev/null +++ b/README.md @@ -0,0 +1,16 @@ +# Apress Source Code + +This repository accompanies [*Low-Level Programming*](http://www.apress.com/9781484224021) by Igor Zhirkov (Apress, 2017). + +[comment]: #cover +![Cover image](9781484224021.jpg) + +Download the files as a zip using the green button, or clone the repository to your machine using Git. + +## Releases + +Release v1.0 corresponds to the code in the published book, without corrections or updates. + +## Contributions + +See the file Contributing.md for more information on how you can contribute to this repository. \ No newline at end of file diff --git a/assignments/1_io_library/stud/lib.inc b/assignments/1_io_library/stud/lib.inc new file mode 100755 index 0000000..8cbcfef --- /dev/null +++ b/assignments/1_io_library/stud/lib.inc @@ -0,0 +1,61 @@ +section .text + +string_length: + xor rax, rax + ret + +print_string: + xor rax, rax + ret + + +print_char: + xor rax, rax + ret + +print_newline: + xor rax, rax + ret + + +print_uint: + xor rax, rax + ret + + +print_int: + xor rax, rax + ret + +string_equals: + xor rax, rax + ret + + +read_char: + xor rax, rax + ret + +section .data +word_buffer times 256 db 0 + +section .text + +read_word: + ret + +; rdi points to a string +; returns rax: number, rdx : length +parse_uint: + xor rax, rax + ret + +; rdi points to a string +; returns rax: number, rdx : length +parse_int: + xor rax, rax + ret + + +string_copy: + ret diff --git a/assignments/1_io_library/stud/test.py b/assignments/1_io_library/stud/test.py new file mode 100755 index 0000000..2885678 --- /dev/null +++ b/assignments/1_io_library/stud/test.py @@ -0,0 +1,346 @@ +#!/usr/bin/python + +import os +import subprocess +import re +from subprocess import CalledProcessError, Popen, PIPE + +#-------helpers--------------- + +def starts_uint( s ): + matches = re.findall('^\d+', s) + if matches: + return (int(matches[0]), len(matches[0])) + else: + return (0, 0) + +def starts_int( s ): + matches = re.findall('^-?\d+', s) + if matches: + return (int(matches[0]), len(matches[0])) + else: + return (0, 0) + +def unsigned_reinterpret(x): + if x < 0: + return x + 2**64 + else: + return x + +def first_or_empty( s ): + sp = s.split() + if sp == [] : + return '' + else: + return sp[0] + +#----------------------------- + +def compile( fname, text ): + f = open( fname + '.asm', 'w') + f.write( text ) + f.close() + + if subprocess.call( ['nasm', '-f', 'elf64', fname + '.asm', '-o', fname+'.o'] ) == 0 and subprocess.call( ['ld', '-o' , fname, fname+'.o'] ) == 0: + print ' ', fname, ': compiled' + return True + else: + print ' ', fname, ': failed to compile' + return False + + +def launch( fname, seed = '' ): + output = '' + try: + p = Popen(['./'+fname], shell=None, stdin=PIPE, stdout=PIPE) + (output, err) = p.communicate(input=seed) + return (output, p.returncode) + except CalledProcessError as exc: + return (exc.output, exc.returncode) + else: + return (output, 0) + + + +def test_asm( text, name = 'dummy', seed = '' ): + if compile( name, text ): + r = launch( name, seed ) + #os.remove( name ) + #os.remove( name + '.o' ) + #os.remove( name + '.asm' ) + return r + return None + +class Test: + name = '' + string = lambda x : x + checker = lambda input, output, code : False + + def __init__(self, name, stringctor, checker): + self.checker = checker + self.string = stringctor + self.name = name + def perform(self, arg): + res = test_asm( self.string(arg), self.name, arg) + if res is None: + return False + (output, code) = res + print '"', arg,'" ->', res + return self.checker( arg, output, code ) + +tests=[ Test('string_length', + lambda v : """section .data + str: db '""" + v + """', 0 + section .text + %include "lib.inc" + global _start + _start: + mov rdi, str + call string_length + mov rdi, rax + mov rax, 60 + syscall""", + lambda i, o, r: r == len(i) + ), + + Test('print_string', + lambda v : """section .data + str: db '""" + v + """', 0 + section .text + %include "lib.inc" + global _start + _start: + mov rdi, str + call print_string + + mov rax, 60 + xor rdi, rdi + syscall""", + lambda i,o,r: i == o), + + Test('string_copy', + lambda v: """section .data + arg1: db '""" + v + """', 0 + arg2: times """ + str(len(v) + 1) + """ db 66 + section .text + %include "lib.inc" + global _start + _start: + mov rdi, arg1 + mov rsi, arg2 + call string_copy + mov rdi, arg2 + call print_string + mov rax, 60 + xor rdi, rdi + syscall""", + lambda i,o,r: i == o), + + Test('print_char', + lambda v:""" section .text + %include "lib.inc" + global _start + _start: + mov rdi, '""" + v + """' + call print_char + mov rax, 60 + xor rdi, rdi + syscall""", + lambda i,o,r: i == o), + + Test('print_uint', + lambda v: """section .text + %include "lib.inc" + global _start + _start: + mov rdi, """ + v + """ + call print_uint + mov rax, 60 + xor rdi, rdi + syscall""", + lambda i, o, r: o == str(unsigned_reinterpret(int(i)))), + + Test('print_int', + lambda v: """section .text + %include "lib.inc" + global _start + _start: + mov rdi, """ + v + """ + call print_int + mov rax, 60 + xor rdi, rdi + syscall""", + lambda i, o, r: o == i), + + Test('read_char', + lambda v:"""section .text + %include "lib.inc" + global _start + _start: + call read_char + mov rdi, rax + mov rax, 60 + syscall""", + lambda i, o, r: (i == "" and r == 0 ) or ord( i[0] ) == r ), + + Test('read_word', + lambda v:"""section .text + %include "lib.inc" + global _start + _start: + call read_word + mov rdi, rax + call print_string + + mov rax, 60 + xor rdi, rdi + syscall""", + lambda i, o, r: first_or_empty(i) == o), + + Test('read_word_length', + lambda v:"""section .text + %include "lib.inc" + global _start + _start: + call read_word + + mov rax, 60 + mov rdi, rdx + syscall""", + lambda i, o, r: len(first_or_empty(i)) == r), + + Test('parse_uint', + lambda v: """section .data + input: db '""" + v + """', 0 + section .text + %include "lib.inc" + global _start + _start: + mov rdi, input + call parse_uint + push rdx + mov rdi, rax + call print_uint + mov rax, 60 + pop rdi + syscall""", + lambda i,o,r: starts_uint(i)[0] == int(o) and r == starts_uint( i )[1]), + + Test('parse_int', + lambda v: """section .data + input: db '""" + v + """', 0 + section .text + %include "lib.inc" + global _start + _start: + mov rdi, input + call parse_int + push rdx + mov rdi, rax + call print_int + pop rdi + mov rax, 60 + syscall""", + lambda i,o,r: (starts_int( i )[1] == 0 and int(o) == 0) or (starts_int(i)[0] == int(o) and r == starts_int( i )[1] )), + + Test('string_equals', + lambda v: """section .data + str1: db '""" + v + """',0 + str2: db '""" + v + """',0 + section .text + %include "lib.inc" + global _start + _start: + mov rdi, str1 + mov rsi, str2 + call string_equals + mov rdi, rax + mov rax, 60 + syscall""", + lambda i,o,r: r == 1), + + Test('string_equals not equals', + lambda v: """section .data + str1: db '""" + v + """',0 + str2: db '""" + v + """!!',0 + section .text + %include "lib.inc" + global _start + _start: + mov rdi, str1 + mov rsi, str2 + call string_equals + mov rdi, rax + mov rax, 60 + syscall""", + lambda i,o,r: r == 0), + + Test('string_copy', + lambda v: """section .data + arg1: db '""" + v + """', 0 + arg2: times """ + str(len(v) + 1) + """ db 66 + section .text + %include "lib.inc" + global _start + _start: + mov rdi, arg1 + mov rsi, arg2 + call string_copy + mov rdi, arg2 + call print_string + mov rax, 60 + xor rdi, rdi + syscall""", + lambda i,o,r: i == o) +] + + +inputs= {'string_length' + : [ 'asdkbasdka', 'qwe qweqe qe', ''], + 'print_string' + : ['ashdb asdhabs dahb', ' ', ''], + 'string_copy' + : ['ashdb asdhabs dahb', ' ', ''], + 'print_char' + : "a c", + 'print_uint' + : ['-1', '12345234121', '0', '12312312', '123123'], + 'print_int' + : ['-1', '-12345234121', '0', '123412312', '123123'], + 'read_char' + : ['-1', '-1234asdasd5234121', '', ' ', '\t ', 'hey ya ye ya', 'hello world', 'asdbaskdbaksvbaskvhbashvbasdasdads wewe'], + 'read_word' + : ['-1', '-1234asdasd5234121', '', ' ', '\t ', 'hey ya ye ya', 'hello world', 'asdbaskdbaksvbaskvhbashvbasdasdads wewe'], + 'read_word_length' + : ['-1', '-1234asdasd5234121', '', ' ', '\t ', 'hey ya ye ya', 'hello world', 'asdbaskdbaksvbaskvhbashvbasdasdads wewe'], + 'parse_uint' + : ["0", "1234567890987654321hehehey", "1" ], + 'parse_int' + : ["0", "1234567890987654321hehehey", "-1dasda", "-eedea", "-123123123", "1" ], + 'string_equals' + : ['ashdb asdhabs dahb', ' ', '', "asd" ], + 'string_equals not equals' + : ['ashdb asdhabs dahb', ' ', '', "asd" ] +} + + +if __name__ == "__main__": + found_error = False + for t in tests: + for arg in inputs[t.name]: + if not found_error: + try: + print ' testing', t.name,'on "'+ arg +'"' + res = t.perform(arg) + if res: + print ' [ ok ]' + else: + print '* [ fail ]' + found_error = True + except: + print '* [ fail ] (exception)' + found_error = True + if found_error: + print 'Not all tests have been passed' + else: + print "Good work, all tests are passed" diff --git a/assignments/1_io_library/teacher/lib.inc b/assignments/1_io_library/teacher/lib.inc new file mode 100755 index 0000000..06cca66 --- /dev/null +++ b/assignments/1_io_library/teacher/lib.inc @@ -0,0 +1,190 @@ +section .text + +string_length: + xor rax, rax +.loop: + cmp byte [rdi+rax], 0 + je .end + inc rax + jmp .loop +.end: + ret + +print_char: + push rdi + mov rdi, rsp + call print_string + pop rdi + ret + +print_newline: + mov rdi, 10 + jmp print_char + +print_string: + push rdi + call string_length + pop rsi + mov rdx, rax + mov rax, 1 + mov rdi, 1 + syscall + ret + +print_uint: + mov rax, rdi + mov rdi, rsp + push 0 + sub rsp, 16 + + dec rdi + mov r8, 10 + +.loop: + xor rdx, rdx + div r8 + or dl, 0x30 + dec rdi + mov [rdi], dl + test rax, rax + jnz .loop + + call print_string + + add rsp, 24 + ret + +print_int: + test rdi, rdi + jns print_uint + push rdi + mov rdi, '-' + call print_char + pop rdi + neg rdi + jmp print_uint + +; returns rax: number, rdx : length +parse_int: + mov al, byte [rdi] + cmp al, '-' + je .signed + jmp parse_uint +.signed: + inc rdi + call parse_uint + neg rax + test rdx, rdx + jz .error + + inc rdx + ret + + .error: + xor rax, rax + ret + +; returns rax: number, rdx : length +parse_uint: + mov r8, 10 + xor rax, rax + xor rcx, rcx +.loop: + movzx r9, byte [rdi + rcx] + cmp r9b, '0' + jb .end + cmp r9b, '9' + ja .end + xor rdx, rdx + mul r8 + and r9b, 0x0f + add rax, r9 + inc rcx + jmp .loop + .end: + mov rdx, rcx + ret + +string_equals: + mov al, byte [rdi] + cmp al, byte [rsi] + jne .no + inc rdi + inc rsi + test al, al + jnz string_equals + mov rax, 1 + ret + .no: + xor rax, rax + ret + + +read_char: + push 0 + xor rax, rax + xor rdi, rdi + mov rsi, rsp + mov rdx, 1 + syscall + pop rax + ret + +section .bss +word_buffer resb 256 + +section .text + +read_word: + push r14 + xor r14, r14 + + .A: + call read_char + cmp al, ' ' + je .A + cmp al, 10 + je .A + cmp al, 13 + je .A + cmp al, 9 + je .A + test al, al + jz .C + + .B: + mov byte [word_buffer + r14], al + inc r14 + + call read_char + cmp al, ' ' + je .C + cmp al, 10 + je .C + cmp al, 13 + je .C + cmp al, 9 + je .C + test al, al + jz .C + cmp r14, 254 + je .C + + jmp .B + + .C: + mov byte [word_buffer + r14], 0 + mov rax, word_buffer + + mov rdx, r14 + pop r14 + ret + +string_copy: + mov dl, byte[rdi] + mov byte[rsi], dl + inc rdi + inc rsi + test dl, dl + jnz string_copy + ret diff --git a/assignments/1_io_library/teacher/test.py b/assignments/1_io_library/teacher/test.py new file mode 100755 index 0000000..2885678 --- /dev/null +++ b/assignments/1_io_library/teacher/test.py @@ -0,0 +1,346 @@ +#!/usr/bin/python + +import os +import subprocess +import re +from subprocess import CalledProcessError, Popen, PIPE + +#-------helpers--------------- + +def starts_uint( s ): + matches = re.findall('^\d+', s) + if matches: + return (int(matches[0]), len(matches[0])) + else: + return (0, 0) + +def starts_int( s ): + matches = re.findall('^-?\d+', s) + if matches: + return (int(matches[0]), len(matches[0])) + else: + return (0, 0) + +def unsigned_reinterpret(x): + if x < 0: + return x + 2**64 + else: + return x + +def first_or_empty( s ): + sp = s.split() + if sp == [] : + return '' + else: + return sp[0] + +#----------------------------- + +def compile( fname, text ): + f = open( fname + '.asm', 'w') + f.write( text ) + f.close() + + if subprocess.call( ['nasm', '-f', 'elf64', fname + '.asm', '-o', fname+'.o'] ) == 0 and subprocess.call( ['ld', '-o' , fname, fname+'.o'] ) == 0: + print ' ', fname, ': compiled' + return True + else: + print ' ', fname, ': failed to compile' + return False + + +def launch( fname, seed = '' ): + output = '' + try: + p = Popen(['./'+fname], shell=None, stdin=PIPE, stdout=PIPE) + (output, err) = p.communicate(input=seed) + return (output, p.returncode) + except CalledProcessError as exc: + return (exc.output, exc.returncode) + else: + return (output, 0) + + + +def test_asm( text, name = 'dummy', seed = '' ): + if compile( name, text ): + r = launch( name, seed ) + #os.remove( name ) + #os.remove( name + '.o' ) + #os.remove( name + '.asm' ) + return r + return None + +class Test: + name = '' + string = lambda x : x + checker = lambda input, output, code : False + + def __init__(self, name, stringctor, checker): + self.checker = checker + self.string = stringctor + self.name = name + def perform(self, arg): + res = test_asm( self.string(arg), self.name, arg) + if res is None: + return False + (output, code) = res + print '"', arg,'" ->', res + return self.checker( arg, output, code ) + +tests=[ Test('string_length', + lambda v : """section .data + str: db '""" + v + """', 0 + section .text + %include "lib.inc" + global _start + _start: + mov rdi, str + call string_length + mov rdi, rax + mov rax, 60 + syscall""", + lambda i, o, r: r == len(i) + ), + + Test('print_string', + lambda v : """section .data + str: db '""" + v + """', 0 + section .text + %include "lib.inc" + global _start + _start: + mov rdi, str + call print_string + + mov rax, 60 + xor rdi, rdi + syscall""", + lambda i,o,r: i == o), + + Test('string_copy', + lambda v: """section .data + arg1: db '""" + v + """', 0 + arg2: times """ + str(len(v) + 1) + """ db 66 + section .text + %include "lib.inc" + global _start + _start: + mov rdi, arg1 + mov rsi, arg2 + call string_copy + mov rdi, arg2 + call print_string + mov rax, 60 + xor rdi, rdi + syscall""", + lambda i,o,r: i == o), + + Test('print_char', + lambda v:""" section .text + %include "lib.inc" + global _start + _start: + mov rdi, '""" + v + """' + call print_char + mov rax, 60 + xor rdi, rdi + syscall""", + lambda i,o,r: i == o), + + Test('print_uint', + lambda v: """section .text + %include "lib.inc" + global _start + _start: + mov rdi, """ + v + """ + call print_uint + mov rax, 60 + xor rdi, rdi + syscall""", + lambda i, o, r: o == str(unsigned_reinterpret(int(i)))), + + Test('print_int', + lambda v: """section .text + %include "lib.inc" + global _start + _start: + mov rdi, """ + v + """ + call print_int + mov rax, 60 + xor rdi, rdi + syscall""", + lambda i, o, r: o == i), + + Test('read_char', + lambda v:"""section .text + %include "lib.inc" + global _start + _start: + call read_char + mov rdi, rax + mov rax, 60 + syscall""", + lambda i, o, r: (i == "" and r == 0 ) or ord( i[0] ) == r ), + + Test('read_word', + lambda v:"""section .text + %include "lib.inc" + global _start + _start: + call read_word + mov rdi, rax + call print_string + + mov rax, 60 + xor rdi, rdi + syscall""", + lambda i, o, r: first_or_empty(i) == o), + + Test('read_word_length', + lambda v:"""section .text + %include "lib.inc" + global _start + _start: + call read_word + + mov rax, 60 + mov rdi, rdx + syscall""", + lambda i, o, r: len(first_or_empty(i)) == r), + + Test('parse_uint', + lambda v: """section .data + input: db '""" + v + """', 0 + section .text + %include "lib.inc" + global _start + _start: + mov rdi, input + call parse_uint + push rdx + mov rdi, rax + call print_uint + mov rax, 60 + pop rdi + syscall""", + lambda i,o,r: starts_uint(i)[0] == int(o) and r == starts_uint( i )[1]), + + Test('parse_int', + lambda v: """section .data + input: db '""" + v + """', 0 + section .text + %include "lib.inc" + global _start + _start: + mov rdi, input + call parse_int + push rdx + mov rdi, rax + call print_int + pop rdi + mov rax, 60 + syscall""", + lambda i,o,r: (starts_int( i )[1] == 0 and int(o) == 0) or (starts_int(i)[0] == int(o) and r == starts_int( i )[1] )), + + Test('string_equals', + lambda v: """section .data + str1: db '""" + v + """',0 + str2: db '""" + v + """',0 + section .text + %include "lib.inc" + global _start + _start: + mov rdi, str1 + mov rsi, str2 + call string_equals + mov rdi, rax + mov rax, 60 + syscall""", + lambda i,o,r: r == 1), + + Test('string_equals not equals', + lambda v: """section .data + str1: db '""" + v + """',0 + str2: db '""" + v + """!!',0 + section .text + %include "lib.inc" + global _start + _start: + mov rdi, str1 + mov rsi, str2 + call string_equals + mov rdi, rax + mov rax, 60 + syscall""", + lambda i,o,r: r == 0), + + Test('string_copy', + lambda v: """section .data + arg1: db '""" + v + """', 0 + arg2: times """ + str(len(v) + 1) + """ db 66 + section .text + %include "lib.inc" + global _start + _start: + mov rdi, arg1 + mov rsi, arg2 + call string_copy + mov rdi, arg2 + call print_string + mov rax, 60 + xor rdi, rdi + syscall""", + lambda i,o,r: i == o) +] + + +inputs= {'string_length' + : [ 'asdkbasdka', 'qwe qweqe qe', ''], + 'print_string' + : ['ashdb asdhabs dahb', ' ', ''], + 'string_copy' + : ['ashdb asdhabs dahb', ' ', ''], + 'print_char' + : "a c", + 'print_uint' + : ['-1', '12345234121', '0', '12312312', '123123'], + 'print_int' + : ['-1', '-12345234121', '0', '123412312', '123123'], + 'read_char' + : ['-1', '-1234asdasd5234121', '', ' ', '\t ', 'hey ya ye ya', 'hello world', 'asdbaskdbaksvbaskvhbashvbasdasdads wewe'], + 'read_word' + : ['-1', '-1234asdasd5234121', '', ' ', '\t ', 'hey ya ye ya', 'hello world', 'asdbaskdbaksvbaskvhbashvbasdasdads wewe'], + 'read_word_length' + : ['-1', '-1234asdasd5234121', '', ' ', '\t ', 'hey ya ye ya', 'hello world', 'asdbaskdbaksvbaskvhbashvbasdasdads wewe'], + 'parse_uint' + : ["0", "1234567890987654321hehehey", "1" ], + 'parse_int' + : ["0", "1234567890987654321hehehey", "-1dasda", "-eedea", "-123123123", "1" ], + 'string_equals' + : ['ashdb asdhabs dahb', ' ', '', "asd" ], + 'string_equals not equals' + : ['ashdb asdhabs dahb', ' ', '', "asd" ] +} + + +if __name__ == "__main__": + found_error = False + for t in tests: + for arg in inputs[t.name]: + if not found_error: + try: + print ' testing', t.name,'on "'+ arg +'"' + res = t.perform(arg) + if res: + print ' [ ok ]' + else: + print '* [ fail ]' + found_error = True + except: + print '* [ fail ] (exception)' + found_error = True + if found_error: + print 'Not all tests have been passed' + else: + print "Good work, all tests are passed" diff --git a/assignments/2_dictionary/teacher/Makefile b/assignments/2_dictionary/teacher/Makefile new file mode 100755 index 0000000..816b978 --- /dev/null +++ b/assignments/2_dictionary/teacher/Makefile @@ -0,0 +1,20 @@ +AFLAGS=-felf64 +ASM=nasm + +all: main + +main: main.o dict.o lib.o + ld -o main main.o dict.o lib.o + +main.o: main.asm colon.inc words.inc + $(ASM) $(AFLAGS) main.asm + +lib.o: lib.asm + $(ASM) $(AFLAGS) lib.asm + +dict.o: dict.asm + $(ASM) $(AFLAGS) dict.asm + + +clean: + rm -f main.o lib.o dict.o main diff --git a/assignments/2_dictionary/teacher/colon.inc b/assignments/2_dictionary/teacher/colon.inc new file mode 100755 index 0000000..3806246 --- /dev/null +++ b/assignments/2_dictionary/teacher/colon.inc @@ -0,0 +1,10 @@ +%define lw 0 + +%macro colon 2 +%%lw: dq lw +db %1, 0 +xt_ %+ %2: + +%define lw %%lw +%endmacro + diff --git a/assignments/2_dictionary/teacher/dict.asm b/assignments/2_dictionary/teacher/dict.asm new file mode 100755 index 0000000..3f391a5 --- /dev/null +++ b/assignments/2_dictionary/teacher/dict.asm @@ -0,0 +1,29 @@ +global find_word +extern string_equals + +section .rodata +msg_noword: db "No such word",0 + +section .text +; rdi = address of a null terminated word name +; rsi = address of the last word +; returns: rax = 0 if not found, otherwise address +find_word: + xor rax, rax +.loop: + test rsi, rsi + jz .end + push rdi + push rsi + add rsi, 8 + call string_equals + pop rsi + pop rdi + test rax, rax + jnz .found + mov rsi, [rsi] + jmp .loop +.found: + mov rax, rsi +.end: + ret diff --git a/assignments/2_dictionary/teacher/lib.asm b/assignments/2_dictionary/teacher/lib.asm new file mode 100755 index 0000000..78cd2b1 --- /dev/null +++ b/assignments/2_dictionary/teacher/lib.asm @@ -0,0 +1,216 @@ +section .text +global string_length +global print_char +global print_newline +global print_string +global print_error +global print_uint +global print_int +global string_equals +global parse_uint +global parse_int +global read_word +global string_copy +global exit + + +string_length: + xor rax, rax +.loop: + cmp byte [rdi+rax], 0 + je .end + inc rax + jmp .loop +.end: + ret + +print_char: + push rdi + mov rdi, rsp + call print_string + pop rdi + ret + +print_newline: + mov rdi, 10 + jmp print_char + +print_error: + push rdi + call string_length + pop rsi + mov rdx, rax + mov rax, 1 + mov rdi, 2 + syscall + ret + +print_string: + push rdi + call string_length + pop rsi + mov rdx, rax + mov rax, 1 + mov rdi, 1 + syscall + ret + +print_uint: + mov rax, rdi + mov rdi, rsp + push 0 + sub rsp, 16 + + dec rdi + mov r8, 10 + +.loop: + xor rdx, rdx + div r8 + or dl, 0x30 + dec rdi + mov [rdi], dl + test rax, rax + jnz .loop + + call print_string + + add rsp, 24 + ret + +print_int: + test rdi, rdi + jns print_uint + push rdi + mov rdi, '-' + call print_char + pop rdi + neg rdi + jmp print_uint + +; returns rax: number, rdx : length +parse_int: + mov al, byte [rdi] + cmp al, '-' + je .signed + jmp parse_uint +.signed: + inc rdi + call parse_uint + neg rax + test rdx, rdx + jz .error + + inc rdx + ret + + .error: + xor rax, rax + ret + +; returns rax: number, rdx : length +parse_uint: + mov r8, 10 + xor rax, rax + xor rcx, rcx +.loop: + movzx r9, byte [rdi + rcx] + cmp r9b, '0' + jb .end + cmp r9b, '9' + ja .end + xor rdx, rdx + mul r8 + and r9b, 0x0f + add rax, r9 + inc rcx + jmp .loop + .end: + mov rdx, rcx + ret + +string_equals: + mov al, byte [rdi] + cmp al, byte [rsi] + jne .no + inc rdi + inc rsi + test al, al + jnz string_equals + mov rax, 1 + ret + .no: + xor rax, rax + ret + + +read_char: + push 0 + xor rax, rax + xor rdi, rdi + mov rsi, rsp + mov rdx, 1 + syscall + pop rax + ret + +read_word: + push r14 + xor r14, r14 + + .A: + push rdi + call read_char + pop rdi + + cmp al, ' ' + je .A + cmp al, 10 + je .A + cmp al, 13 + je .A + cmp al, 9 + je .A + + .B: + mov byte [rdi + r14], al + inc r14 + + push rdi + call read_char + pop rdi + cmp al, ' ' + je .C + cmp al, 10 + je .C + cmp al, 13 + je .C + cmp al, 9 + je .C + test al, al + jz .C + cmp r14, 254 + je .C + + jmp .B + + .C: + mov byte [rdi + r14], 0 + mov rax, rdi + + pop r14 + ret + +string_copy: + mov dl, byte[rdi] + mov byte[rsi], dl + inc rdi + inc rsi + test dl, dl + jnz string_copy + ret + + +exit: + mov rax, 60 + syscall diff --git a/assignments/2_dictionary/teacher/main.asm b/assignments/2_dictionary/teacher/main.asm new file mode 100755 index 0000000..a2af1c2 --- /dev/null +++ b/assignments/2_dictionary/teacher/main.asm @@ -0,0 +1,56 @@ +section .text +%include "colon.inc" + +extern read_word +extern find_word +extern print_newline +extern print_string +extern print_error +extern string_length +extern exit + +global _start + +section .rodata +msg_noword: db "No such word",0 + + +%include "words.inc" + +section .text +_start: + push rbp + mov rbp, rsp + sub rsp, 256 + mov rdi, rsp + call read_word + mov rdi, rax + mov rsi, lw + call find_word + test rax, rax + jz .bad + + add rax, 8 + push rax + mov rax, [rsp] + mov rdi, rax + call string_length + pop rdi + add rdi, rax + inc rdi + call print_string + mov rsp, rbp + pop rbp + mov rdi, 0 + call exit + +.bad: + mov rdi, msg_noword + call print_error + + mov rsp, rbp + pop rbp + mov rdi, 0 + call exit + + diff --git a/assignments/2_dictionary/teacher/words.inc b/assignments/2_dictionary/teacher/words.inc new file mode 100755 index 0000000..04c6f58 --- /dev/null +++ b/assignments/2_dictionary/teacher/words.inc @@ -0,0 +1,8 @@ +colon "hey", hey +db "hoho",0 + +colon "test", test +db "hihi", 0 + +colon "tost", tost +db "haha", 0 diff --git a/assignments/forth-bootstrap/teacher/Makefile b/assignments/forth-bootstrap/teacher/Makefile new file mode 100755 index 0000000..175f883 --- /dev/null +++ b/assignments/forth-bootstrap/teacher/Makefile @@ -0,0 +1,30 @@ +# ------------------------------------------------ +# Forthress, a Forth dialect +# +# Author: igorjirkov@gmail.com +# Date : 15-10-2016 +# +# ------------------------------------------------ + +ASM = nasm +FLAGS = -felf64 -g -Isrc/ +LINKER = ld + +all: bin/forthress + +bin/forthress: obj/forthress.o obj/util.o + mkdir -p bin + ld -o bin/forthress obj/forthress.o obj/util.o + +obj/forthress.o: src/forthress.asm src/macro.inc src/words.inc src/util.inc + mkdir -p obj + $(ASM) $(FLAGS) src/forthress.asm -o obj/forthress.o + +obj/util.o: src/util.inc src/util.asm + mkdir -p obj + $(ASM) $(FLAGS) src/util.asm -o obj/util.o +clean: + rm -rf build obj + +.PHONY: clean + diff --git a/assignments/forth-bootstrap/teacher/mwe/forth.asm b/assignments/forth-bootstrap/teacher/mwe/forth.asm new file mode 100755 index 0000000..be6f9f3 --- /dev/null +++ b/assignments/forth-bootstrap/teacher/mwe/forth.asm @@ -0,0 +1,80 @@ +%include "lib.inc" + +global _start + +%define pc r15 +%define w r14 +%define rstack r13 + +section .bss +rstack_start: resq 1024 +input_buf: resb 1024 + + +section .text +main_stub: dq xt_main +xt_drop: dq i_drop +i_drop: + add rsp, 8 + jmp next +xt_init: dq i_init +i_init: + mov rstack, rstack_start + mov pc, main_stub + jmp next + +xt_docol: dq i_docol +i_docol: + sub rstack, 8 + mov [rstack], pc + add w, 8 + mov pc, w + jmp next + +xt_exit: dq i_exit +i_exit: + mov pc, [rstack] + add rstack, 8 + jmp next + +xt_word: dq i_word +i_word: + pop rdi + call read_word + push rdx + jmp next + +xt_prints: dq i_prints +i_prints: + pop rdi + call print_string + jmp next + +xt_bye: dq i_bye +i_bye: + mov rax, 60 + xor rdi, rdi + syscall + +xt_inbuf: dq i_inbuf +i_inbuf: + push qword input_buf + jmp next + +xt_main: dq i_docol + dq xt_inbuf + dq xt_word + dq xt_drop + dq xt_inbuf + dq xt_prints + dq xt_bye + +next: + mov w, [pc] + add pc, 8 + jmp [w] + +_start: jmp i_init + + + diff --git a/assignments/forth-bootstrap/teacher/mwe/lib.inc b/assignments/forth-bootstrap/teacher/mwe/lib.inc new file mode 100755 index 0000000..a11f19c --- /dev/null +++ b/assignments/forth-bootstrap/teacher/mwe/lib.inc @@ -0,0 +1,190 @@ +section .text + +string_length: + xor rax, rax +.loop: + cmp byte [rdi+rax], 0 + je .end + inc rax + jmp .loop +.end: + ret + +print_char: + push rdi + mov rdi, rsp + call print_string + pop rdi + ret + +print_newline: + mov rdi, 10 + jmp print_char + +print_string: + push rdi + call string_length + pop rsi + mov rdx, rax + mov rax, 1 + mov rdi, 1 + syscall + ret + +print_uint: + mov rax, rdi + mov rdi, rsp + push 0 + sub rsp, 16 + + dec rdi + mov r8, 10 +.loop: + xor rdx, rdx + div r8 + or dl, 0x30 + dec rdi + mov [rdi], dl + test rax, rax + jnz .loop + + call print_string + + add rsp, 24 + ret + +print_int: + test rdi, rdi + jns print_uint + push rdi + mov rdi, '-' + call print_char + pop rdi + neg rdi + jmp print_uint + +; returns rax: number, rdx : length +parse_int: + mov al, byte [rdi] + cmp al, '-' + je .signed + jmp parse_uint +.signed: + inc rdi + call parse_uint + neg rax + test rdx, rdx + jz .error + + inc rdx + ret + + .error: + xor rax, rax + ret + +; returns rax: number, rdx : length +parse_uint: + mov r8, 10 + xor rax, rax + xor rcx, rcx +.loop: + movzx r9, byte [rdi + rcx] + cmp r9b, '0' + jb .end + cmp r9b, '9' + ja .end + xor rdx, rdx + mul r8 + and r9b, 0x0f + add rax, r9 + inc rcx + jmp .loop + .end: + mov rdx, rcx + ret + +string_equals: + mov al, byte [rdi] + cmp al, byte [rsi] + jne .no + inc rdi + inc rsi + test al, al + jnz string_equals + mov rax, 1 + ret + .no: + xor rax, rax + ret + + +read_char: + push 0 + xor rax, rax + xor rdi, rdi + mov rsi, rsp + mov rdx, 1 + syscall + pop rax + ret + +section .text + +read_word: + push r14 + xor r14, r14 + + .A: + push rdi + call read_char + pop rdi + cmp al, ' ' + je .A + cmp al, 10 + je .A + cmp al, 13 + je .A + cmp al, 9 + je .A + test al, al + jz .C + + .B: + mov byte [rdi + r14], al + inc r14 + + push rdi + call read_char + pop rdi + cmp al, ' ' + je .C + cmp al, 10 + je .C + cmp al, 13 + je .C + cmp al, 9 + je .C + test al, al + jz .C + cmp r14, 254 + je .C + + jmp .B + + .C: + mov byte [rdi + r14], 0 + mov rax, rdi + + mov rdx, r14 + pop r14 + ret + +string_copy: + mov dl, byte[rdi] + mov byte[rsi], dl + inc rdi + inc rsi + test dl, dl + jnz string_copy + ret diff --git a/assignments/forth-bootstrap/teacher/mwe/macro.asm b/assignments/forth-bootstrap/teacher/mwe/macro.asm new file mode 100755 index 0000000..9b45bbd --- /dev/null +++ b/assignments/forth-bootstrap/teacher/mwe/macro.asm @@ -0,0 +1,33 @@ +%define _lw 0 +%macro native 3 + section .data + wh_ %+ %2 : dq _lw + %define _lw wh %+ %2 + db %1, 0 + db 0 | %3 + xt_ %+ %2 : dq i_ %+ %2 + section .text + i_ %+ %2: + %define _lw wh_%+ %2 + +%endmacro + +%macro native 2 +native %1, %2, 0 +%endmacro + +%macro colon 3 +section .data + wh_ %+ %2 : dq _lw + %define _lw wh_ %+ %2 + db %1, 0 + db 0 | %3 + + + xt_ %+ %2 : dq i_docol +%endmacro + +%macro colon 2 +colon %1, %2, 0 +%endmacro + diff --git a/assignments/forth-bootstrap/teacher/src/forthress.asm b/assignments/forth-bootstrap/teacher/src/forthress.asm new file mode 100755 index 0000000..68922d8 --- /dev/null +++ b/assignments/forth-bootstrap/teacher/src/forthress.asm @@ -0,0 +1,49 @@ +; ------------------------------------------------ +; Forthress, a Forth dialect +; +; Author: igorjirkov@gmail.com +; Date : 15-10-2016 +; +; This is the main Forthress file which defines the entry point +; Please define words inside "words.inc" +; last_word is dependent, it should be placed after all words are defined +; ------------------------------------------------ + +global _start +%include "macro.inc" +%include "util.inc" + +%define pc r15 +%define w r14 +%define rstack r13 + +section .text + +%include "words.inc" + +section .bss + +resq 1023 +rstack_start: resq 1 + +input_buf: resb 1024 +user_dict: resq 65536 +user_mem: resq 65536 + +section .data +state: dq 0 +last_word: dq _lw +here: dq user_dict + +section .rodata +msg_no_such_word: db ": no such word", 10, 0 + +section .text +next: + mov w, pc + add pc, 8 + mov w, [w] + jmp [w] + +_start: jmp i_init + diff --git a/assignments/forth-bootstrap/teacher/src/macro.inc b/assignments/forth-bootstrap/teacher/src/macro.inc new file mode 100755 index 0000000..130347e --- /dev/null +++ b/assignments/forth-bootstrap/teacher/src/macro.inc @@ -0,0 +1,65 @@ +%define _lw 0 +%macro native 3 + section .data + wh_ %+ %2 : dq _lw + %define _lw wh %+ %2 + db 0 ; to mark the name start + db %1, 0 + db %3 + + + xt_ %+ %2 : dq i_ %+ %2 + section .text + i_ %+ %2: + %define _lw wh_%+ %2 +%endmacro + +%macro native 2 +native %1, %2, 0 +%endmacro + +%macro colon 3 +section .data + wh_ %+ %2 : dq _lw + %define _lw wh_ %+ %2 + db 0 ; to mark the name start + db %1, 0 + db %3 + + + xt_ %+ %2 : dq i_docol +%endmacro + +%macro colon 2 +colon %1, %2, 0 +%endmacro + +%macro rpush 1 + sub rstack, 8 + mov qword [rstack], %1 +%endmacro + +%macro rpop 1 + mov %1, qword [rstack] + add rstack, 8 +%endmacro + + +%macro const 2 +%defstr %%__cnst_str %1 +native %%__cnst_str, %1 + push qword %2 + jmp next +%endmacro + + +%macro branch 1 +dq xt_branch +dq %1 - $ - 8 +%endmacro + +%macro branch0 1 +dq xt_branch0 +dq %1 - $ - 8 +%endmacro + diff --git a/assignments/forth-bootstrap/teacher/src/util.asm b/assignments/forth-bootstrap/teacher/src/util.asm new file mode 100755 index 0000000..7446b32 --- /dev/null +++ b/assignments/forth-bootstrap/teacher/src/util.asm @@ -0,0 +1,199 @@ +global string_length +global print_newline +global print_char +global print_string +global print_uint +global print_int +global parse_int +global parse_uint +global string_equals +global read_char +global read_word +global string_copy + +section .text +string_length: + xor rax, rax +.loop: + cmp byte [rdi+rax], 0 + je .end + inc rax + jmp .loop +.end: + ret + +print_newline: + mov rdi, 10 +print_char: + push rdi + mov rdi, rsp + call print_string + pop rdi + ret + +print_string: + push rdi + call string_length + pop rsi + mov rdx, rax + mov rax, 1 + mov rdi, 1 + syscall + ret + +print_uint: + mov rax, rdi + mov rdi, rsp + push 0 + sub rsp, 16 + + dec rdi + mov r8, 10 +.loop: + xor rdx, rdx + div r8 + or dl, 0x30 + dec rdi + mov [rdi], dl + test rax, rax + jnz .loop + + call print_string + + add rsp, 24 + ret + +print_int: + test rdi, rdi + jns print_uint + push rdi + mov rdi, '-' + call print_char + pop rdi + neg rdi + jmp print_uint + +; returns rax: number, rdx : length +parse_int: + mov al, byte [rdi] + cmp al, '-' + je .signed + jmp parse_uint +.signed: + inc rdi + call parse_uint + neg rax + test rdx, rdx + jz .error + + inc rdx + ret + + .error: + xor rax, rax + ret + +; returns rax: number, rdx : length +parse_uint: + mov r8, 10 + xor rax, rax + xor rcx, rcx +.loop: + movzx r9, byte [rdi + rcx] + cmp r9b, '0' + jb .end + cmp r9b, '9' + ja .end + xor rdx, rdx + mul r8 + and r9b, 0x0f + add rax, r9 + inc rcx + jmp .loop + .end: + mov rdx, rcx + ret + +string_equals: + mov al, byte [rdi] + cmp al, byte [rsi] + jne .no + inc rdi + inc rsi + test al, al + jnz string_equals + mov rax, 1 + ret + .no: + xor rax, rax + ret + +read_char: + push 0 + xor rax, rax + xor rdi, rdi + mov rsi, rsp + mov rdx, 1 + syscall + pop rax + ret + +section .text + +read_word: + push r14 + xor r14, r14 + + .A: + push rdi + call read_char + pop rdi + cmp al, ' ' + je .A + cmp al, 10 + je .A + cmp al, 13 + je .A + cmp al, 9 + je .A + test al, al + jz .C + + .B: + mov byte [rdi + r14], al + inc r14 + + push rdi + call read_char + pop rdi + cmp al, ' ' + je .C + cmp al, 10 + je .C + cmp al, 13 + je .C + cmp al, 9 + je .C + test al, al + jz .C + cmp r14, 254 + je .C + + jmp .B + + .C: + mov byte [rdi + r14], 0 + mov rax, rdi + + mov rdx, r14 + pop r14 + ret + +string_copy: + mov dl, byte[rdi] + mov byte[rsi], dl + inc rdi + inc rsi + test dl, dl + jnz string_copy + ret diff --git a/assignments/forth-bootstrap/teacher/src/util.inc b/assignments/forth-bootstrap/teacher/src/util.inc new file mode 100755 index 0000000..b54df70 --- /dev/null +++ b/assignments/forth-bootstrap/teacher/src/util.inc @@ -0,0 +1,17 @@ +%ifndef _UTIL_ +%define _UTIL_ + +extern string_length +extern print_newline +extern print_char +extern print_string +extern print_uint +extern print_int +extern parse_int +extern parse_uint +extern string_equals +extern read_char +extern read_word +extern string_copy + +%endif diff --git a/assignments/forth-bootstrap/teacher/src/words.inc b/assignments/forth-bootstrap/teacher/src/words.inc new file mode 100755 index 0000000..3094a27 --- /dev/null +++ b/assignments/forth-bootstrap/teacher/src/words.inc @@ -0,0 +1,482 @@ +; ------------------------------------------------ +; Forthress, a Forth dialect +; +; This file is storing the predefined words +; Check README.md in the root directory for +; word semantics +; +; Author: igorjirkov@gmail.com +; Date : 15-10-2016 +; +; ------------------------------------------------ + +; ( a -- ) +native "drop", drop + add rsp, 8 + jmp next + +; ( a b -- b a ) +native "swap", swap + pop rax + pop rdx + push rax + push rdx + jmp next + +; ( a -- a a ) +native "dup", dup + push qword [rsp] + jmp next + +; ( a b c -- b c a ) +native "rot", rot + pop rcx + pop rdx + pop rax + push rdx + push rcx + push rax + jmp next + +; ( y x -- [ x + y ] ) +native "+", plus + pop rax + add [rsp], rax + jmp next + +; ( y x -- [ x * y ] ) +native "*", mul + pop rax + pop rdx + imul rdx + push rax + jmp next + +; ( y x -- [ x / y ] ) +native "/", div + pop rcx + pop rax + cqo + idiv rcx + push rax + jmp next + +; ( y x -- [ x mod y ] ) +native "%", mod + pop rcx + pop rax + cqo + idiv rcx + push rdx + jmp next +; ( y x -- [x - y] ) +native "-", minus + pop rax + sub [rsp], rax + jmp next + +; ( a -- a' ) +; a' = 0 if a != 0 +; a' = 1 if a == 0 +native "not", not + pop rax + test rax, rax + setz al + movzx rax, al + push rax + jmp next + +; ( a b -- c ) +; c = 1 if a == b +; c = 0 if a != b +native "=", equals + pop rax + pop rdx + cmp rax, rdx + sete al + movzx rax, al + push rax + jmp next + +; ( str -- len ) +native "count", count + pop rdi + call string_length + push rax + jmp next + +; Drops element from stack and sends it to stdout +native ".", dot + pop rdi + call print_int + call print_newline + jmp next + +; Shows stack contents. Does not pop elements +native ".S", show_stack + mov rcx, rsp + .loop: + cmp rcx, [stack_base] + jae next + mov rdi, [rcx] + push rcx + call print_int + call print_newline + pop rcx + add rcx, 8 + jmp .loop + +section .rodata + interpreter_stub: dq xt_interpreter + +; Stores the data stack base. It is useful for .S +section .data + stack_base: dq 0 +native "init", init + mov qword [state], 0 + mov rstack, rstack_start + mov pc, interpreter_stub + cmp qword [stack_base], 0 + je .first + mov rsp, [stack_base] + jmp next + .first: + mov [stack_base], rsp + jmp next + +; This is the implementation of any colon-word. +; The XT itself is not used, but the implementation (i_docol) is. + +native "docol", docol + rpush pc + add w, 8 + mov pc, w + jmp next + +; Exit from colon word +native "exit", exit + rpop pc + jmp next + +; Pop from data stack into return stack +native ">r", to_r + pop rax + rpush rax + jmp next + +; Push from return stack into data stack +native "r>", from_r + rpop rax + push rax + jmp next + +; Non-destructive copy from the top of return stack +; to the top of data stack +native "r@", r_fetch + push qword [rstack] + jmp next + +colon "constant", constant + +; ( str -- header_addr ) +native "find", find + mov rsi, [last_word] +.loop: + mov rdi, [rsp] + push rsi + add rsi, 9 + call string_equals + pop rsi + test rax, rax + jnz .found + + mov rsi, [rsi] + test rsi, rsi + jnz .loop +.not_found: + mov qword [rsp], 0 + push 0 + jmp next +.found: + mov [rsp], rsi + jmp next + +; ( word_addr -- xt ) +; Converts word header start address to the +; execution token +native "cfa", cfa + pop rsi + add rsi, 9 + .loop: + mov al, [rsi] + test al, al + jz .end + inc rsi + jmp .loop + + .end: + add rsi, 2 + push rsi + jmp next + +; ( c -- ) +; Outputs a single character to stdout +native "emit", emit + pop rdi + call print_char + jmp next + + +; ( addr -- len ) +; Reads word from stdin and stores it starting at address +; Word length is pushed into stack +native "word", word + pop rdi + call read_word + push rdx + jmp next + +; ( str -- len num ) +; Parses an integer from string +native "number", number + pop rdi + call parse_int + push rax + push rdx + jmp next + +; ( addr -- ) +; Prints a null-terminated string +native "prints", prints + pop rdi + call print_string + jmp next + +; Exits Forthress +native "bye", bye + mov rax, 60 + xor rdi, rdi + syscall + +; ( call_num a1 a2 a3 a4 a5 a6 -- new_rax ) +; Executes syscall +; The following registers store arguments (according to ABI) +; rdi , rsi , rdx , r10 , r8 and r9 +native "syscall", syscall + pop r9 + pop r8 + pop r10 + pop rdx + pop rsi + pop rdi + pop rax + syscall + push rax + jmp next + +; Jump to a location. Location is an offset relative to the argument end +; F.e.: |xt_branch| 24 | +; ^ branch adds 24 to this address and stores it in PC +; Branch is a compile-only word. +native "branch", branch + add pc, [pc] + add pc, 8 + jmp next + +; Jump to a location if TOS = 0. Location is calculated in a similar way +; F.e.: |xt_branch| 24 | +; ^ branch adds 24 to this address and stores it in PC +; Branch0 is a compile-only word. +native "0branch", branch0 + pop rax + test rax, rax + jnz .skip + add pc, [pc] + .skip: + add pc, 8 + jmp next + +; Pushes a value immediately following this XT +native "lit", lit + push qword [pc] + add pc, 8 + jmp next + +; Address of the input buffer (is used by interpreter/compiler) +const inbuf, input_buf + +; Address of user memory. +const mem, user_mem + +; Last word address +const last_word, last_word + +; State cell address. +; The state cell stores either 1 (compilation mode) or 0 (interpretation mode) +const state, state + +const here, [here] + +; ( xt -- ) +; Execute word with this execution token on TOS +native "execute", execute + pop rax + mov w, rax + jmp [rax] + + +; ( addr -- value ) +; Fetch value from memory +native "@", fetch + pop rax + push qword[rax] + jmp next + +; ( val addr -- ) +; Store value by address +native "!", write + pop rax + pop rdx + mov [rdx], rax + jmp next + +; ( addr -- char ) +; Read one byte starting at addr +native "@c", fetch_char + pop rax + movzx rax, byte [rax] + push rax + jmp next + +; ( x -- ) +; Add x to the word being defined +native ",", comma + mov rax, [here] + pop qword [rax] + add qword [here], 8 + jmp next + +; ( c -- ) +; Add a single byte to the word being defined +native "c,", char_comma + mov rax, [here] + pop rdx + mov [rax], dl + add qword[here], 1 + jmp next + +; ( name flags -- ) +; Create an entry in the dictionary +; name is the new name +; only immediate flag is implemented ATM +native "create", create + ; link + mov rcx, [last_word] + mov rsi, [here] + mov [rsi], rcx + mov [last_word], rsi + add rsi, 8 + mov byte [rsi], 0 + inc rsi + + ; name + pop rdi + push rsi + call string_copy + pop rsi + push rsi + mov rdi, rsi + call string_length + pop rsi + add rsi, rax + ; flags + inc rsi + pop rax + mov [rsi], al + inc rsi + + mov [here], rsi + jmp next + +; Read word from stdin and start defining it +colon ":", colon + .restart: + dq xt_inbuf, xt_word + branch0 .restart + dq xt_lit, 0, xt_inbuf, xt_create + dq xt_state, xt_lit, 1, xt_write + dq xt_lit, i_docol, xt_comma + dq xt_exit + +; End the current word definition +colon ";", semicolon, 1 + dq xt_state, xt_lit, 0, xt_write + dq xt_lit, xt_exit, xt_comma + dq xt_exit + +; Forthress interpreter +; Check the 'branch' and 'branch0' macros in 'macro.inc' +colon "interpreter", interpreter +.start: + dq xt_inbuf, xt_word + branch0 .end_of_input + + dq xt_inbuf, xt_find ; find in dict + + dq xt_dup + branch0 .number ; if not found, try to parse as a number + dq xt_cfa + + ; if compile + dq xt_state, xt_fetch + branch0 .interpreting + + ; if is immediate: + dq xt_dup + dq xt_lit, 1, xt_minus, xt_fetch_char, xt_not + branch0 .interpreting + + ; compile + dq xt_comma + branch .start + + .interpreting: + dq xt_execute + branch .start + + .number: + dq xt_drop + dq xt_drop + dq xt_inbuf + dq xt_number + branch0 .no_word + + dq xt_state, xt_fetch ; if interpreting, that's it + branch0 .start + ; when compiling, check if it was after a branch + dq xt_here, xt_lit, 8, xt_minus + dq xt_lit, xt_branch0 + dq xt_equals, xt_not + branch0 .is_branch + + dq xt_here, xt_lit, 8, xt_minus + dq xt_lit, xt_branch + dq xt_equals, xt_not + branch0 .is_branch + + dq xt_lit, xt_lit, xt_comma + +.is_branch: + dq xt_comma + + branch .start + + .no_word: + dq xt_drop, xt_inbuf, xt_prints + dq xt_lit, msg_no_such_word, xt_prints + branch .start + + .end_of_input: + dq xt_bye + dq xt_exit + diff --git a/listings/appendix_gdb/call_stack/call_stack.c b/listings/appendix_gdb/call_stack/call_stack.c new file mode 100755 index 0000000..d254786 --- /dev/null +++ b/listings/appendix_gdb/call_stack/call_stack.c @@ -0,0 +1,17 @@ +#include + +void g(int garg) { + int glocal = 99; + puts("Inside g"); +} + +void f(int farg) { + int flocal = 44; + g( flocal ); +} + +int main( void ) { + f( 42 ); + return 0; +} + diff --git a/listings/appendix_gdb/print_rax_2/print_rax_2.asm b/listings/appendix_gdb/print_rax_2/print_rax_2.asm new file mode 100755 index 0000000..c6e5792 --- /dev/null +++ b/listings/appendix_gdb/print_rax_2/print_rax_2.asm @@ -0,0 +1,32 @@ +section .data +codes: +db '0123456789ABCDEF' + +section .text +global _start +_start: +mov rax, 0x1122334455667788 + +mov rdi, 1 +mov rdx, 1 +mov rcx, 64 +.loop: +push rax +sub rcx, 4 +sar rax, cl +and rax, 0xf + +lea rsi, [codes + rax] +mov rax, 1 + +push rcx +syscall +pop rcx + +pop rax +test rcx, rcx +jnz .loop + +mov rax, 60 ; invoke 'close' system call +xor rdi, rdi +syscall diff --git a/listings/appendix_make/Makefile_simple/Makefile_simple b/listings/appendix_make/Makefile_simple/Makefile_simple new file mode 100755 index 0000000..b5b185f --- /dev/null +++ b/listings/appendix_make/Makefile_simple/Makefile_simple @@ -0,0 +1,11 @@ +program: main.o lib.o + ld -o program main.o lib.o + +lib.o: lib.asm + nasm -f elf64 -o lib.o lib.asm + +main.o: main.asm + nasm -f elf64 -o main.o main.asm + +clean: + rm main.o lib.o program diff --git a/listings/appendix_make/Makefile_vars/Makefile_vars b/listings/appendix_make/Makefile_vars/Makefile_vars new file mode 100755 index 0000000..4d5db77 --- /dev/null +++ b/listings/appendix_make/Makefile_vars/Makefile_vars @@ -0,0 +1,17 @@ +AS = nasm +LD = ld +ASFLAGS = -f elf64 + +program: main.o lib.o + $(LD) -o program main.o lib.o + +lib.o: lib.asm + $(AS) $(ASFLAGS) -o lib.o lib.asm + +main.o: main.asm + $(AS) $(ASFLAGS) -o main.o main.asm + +clean: + rm main.o lib.o program + +.PHONY: clean diff --git a/listings/appendix_make/makefile_autovars/makefile_autovars b/listings/appendix_make/makefile_autovars/makefile_autovars new file mode 100755 index 0000000..545e085 --- /dev/null +++ b/listings/appendix_make/makefile_autovars/makefile_autovars @@ -0,0 +1,16 @@ +CC = gcc +CFLAGS = -std=c11 -Wall +LD = gcc + +all: main + +main: main.o lib.o + $(LD) $^ -o $@ + +%.o: %.c %.h + $(CC) $(CFLAGS) -c $< -o $@ + +clean: + rm -f *.o main + +.PHONY: clean diff --git a/listings/chap10/file/file.h b/listings/chap10/file/file.h new file mode 100755 index 0000000..529aa5a --- /dev/null +++ b/listings/chap10/file/file.h @@ -0,0 +1,6 @@ +#ifndef _FILE_H_ +#define _FILE_H_ + +void a(void); + +#endif diff --git a/listings/chap10/fun_decl_def/fun_decl_def.c b/listings/chap10/fun_decl_def/fun_decl_def.c new file mode 100755 index 0000000..e1e6584 --- /dev/null +++ b/listings/chap10/fun_decl_def/fun_decl_def.c @@ -0,0 +1,7 @@ +/* This is declaration */ +void f( int x ); + +/* This is definition */ +void f( int x ) { + puts( "Hello!" ); +} diff --git a/listings/chap10/fun_mutual_recursive_bad/fun_mutual_recursive_bad.c b/listings/chap10/fun_mutual_recursive_bad/fun_mutual_recursive_bad.c new file mode 100755 index 0000000..cd8fbe0 --- /dev/null +++ b/listings/chap10/fun_mutual_recursive_bad/fun_mutual_recursive_bad.c @@ -0,0 +1,7 @@ +void f(void) { + g(); /* What is `g`, asks mr. Compiler? */ +} + +void g(void) { + f(); +} diff --git a/listings/chap10/fun_proto_omit_arguments/fun_proto_omit_arguments.c b/listings/chap10/fun_proto_omit_arguments/fun_proto_omit_arguments.c new file mode 100755 index 0000000..2875eb5 --- /dev/null +++ b/listings/chap10/fun_proto_omit_arguments/fun_proto_omit_arguments.c @@ -0,0 +1,4 @@ +int square( int x ); +/* same as */ +int square( int ); + diff --git a/listings/chap10/fun_sc_1/fun_sc_1.c b/listings/chap10/fun_sc_1/fun_sc_1.c new file mode 100755 index 0000000..e7e5458 --- /dev/null +++ b/listings/chap10/fun_sc_1/fun_sc_1.c @@ -0,0 +1,5 @@ +int square( int x ) { return x * x; } + +... +int z = square(5); + diff --git a/listings/chap10/fun_sc_2/fun_sc_2.c b/listings/chap10/fun_sc_2/fun_sc_2.c new file mode 100755 index 0000000..d04e125 --- /dev/null +++ b/listings/chap10/fun_sc_2/fun_sc_2.c @@ -0,0 +1,8 @@ +int square( int x ); + +... +int z = square(5); + +... + +int square( int x ) { return x * x; } diff --git a/listings/chap10/fun_sc_3/fun_sc_3.c b/listings/chap10/fun_sc_3/fun_sc_3.c new file mode 100755 index 0000000..da1e455 --- /dev/null +++ b/listings/chap10/fun_sc_3/fun_sc_3.c @@ -0,0 +1,3 @@ +int z = square( 5 ); +... +int square( int x ) { return x * x; } diff --git a/listings/chap10/glob_build/glob_build b/listings/chap10/glob_build/glob_build new file mode 100755 index 0000000..04340c0 --- /dev/null +++ b/listings/chap10/glob_build/glob_build @@ -0,0 +1,3 @@ +> gcc -c -std=c89 -pedantic -Wall -o main.o main.c +> gcc -c -std=c89 -pedantic -Wall -o other.o other.c +> gcc -o main main.o other.o diff --git a/listings/chap10/glob_nm/glob_nm b/listings/chap10/glob_nm/glob_nm new file mode 100755 index 0000000..bfe1055 --- /dev/null +++ b/listings/chap10/glob_nm/glob_nm @@ -0,0 +1,12 @@ +> nm main.o +0000000000000000 T main + U printf +0000000000000004 C x + +> nm other.o +0000000000000000 D x + +> nm main +0000000000400526 T main + U printf@@GLIBC_2.2.5 +0000000000601038 D x diff --git a/listings/chap10/ifdef_else_ex/ifdef_else_ex.c b/listings/chap10/ifdef_else_ex/ifdef_else_ex.c new file mode 100755 index 0000000..1446007 --- /dev/null +++ b/listings/chap10/ifdef_else_ex/ifdef_else_ex.c @@ -0,0 +1,5 @@ +#ifdef SYMBOL +/*code*/ +#else +/*other code*/ +#endif diff --git a/listings/chap10/ifdef_ex/ifdef_ex.c b/listings/chap10/ifdef_ex/ifdef_ex.c new file mode 100755 index 0000000..007ef5c --- /dev/null +++ b/listings/chap10/ifdef_ex/ifdef_ex.c @@ -0,0 +1,3 @@ +#ifdef SYMBOL +/*code*/ +#endif diff --git a/listings/chap10/ifdef_pitfall_sig/ifdef_pitfall_sig.c b/listings/chap10/ifdef_pitfall_sig/ifdef_pitfall_sig.c new file mode 100755 index 0000000..40f1497 --- /dev/null +++ b/listings/chap10/ifdef_pitfall_sig/ifdef_pitfall_sig.c @@ -0,0 +1,7 @@ +#ifdef SOMEFLAG +int foo() { +#else + void foo() { +#endif + /* ... */ + } diff --git a/listings/chap10/ifndef_ex/ifndef_ex.c b/listings/chap10/ifndef_ex/ifndef_ex.c new file mode 100755 index 0000000..fc1f440 --- /dev/null +++ b/listings/chap10/ifndef_ex/ifndef_ex.c @@ -0,0 +1,5 @@ +#ifndef MYFLAG +/*code*/ +#else +/*other code*/ +#endif diff --git a/listings/chap10/inc_guard_motivation/inc_guard_motivation.c b/listings/chap10/inc_guard_motivation/inc_guard_motivation.c new file mode 100755 index 0000000..2e19182 --- /dev/null +++ b/listings/chap10/inc_guard_motivation/inc_guard_motivation.c @@ -0,0 +1,12 @@ +/* a.h */ +void a(void); + +/* b.h */ +#include "a.h" +void b(void); + + +/* main.c */ +#include "a.h" +#include "b.h" + diff --git a/listings/chap10/incomplete_type_example/incomplete_type_example.c b/listings/chap10/incomplete_type_example/incomplete_type_example.c new file mode 100755 index 0000000..1fb4399 --- /dev/null +++ b/listings/chap10/incomplete_type_example/incomplete_type_example.c @@ -0,0 +1,5 @@ +struct llist_t; + +struct llist_t* f() { ... } /* ok */ +struct llist_t g(); /* ok */ +struct llist_t g() { ... } /* bad */ diff --git a/listings/chap10/ldd_locating_libc/ldd_locating_libc b/listings/chap10/ldd_locating_libc/ldd_locating_libc new file mode 100755 index 0000000..28f1ad4 --- /dev/null +++ b/listings/chap10/ldd_locating_libc/ldd_locating_libc @@ -0,0 +1,5 @@ +> gcc main.c -o main + > ldd main + linux-vdso.so.1 (0x00007fff4e7fc000) + libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f2b7f6bf000) +/lib64/ld-linux-x86-64.so.2 (0x00007f2b7fa76000) diff --git a/listings/chap10/list_definition/list_definition.c b/listings/chap10/list_definition/list_definition.c new file mode 100755 index 0000000..eeb318f --- /dev/null +++ b/listings/chap10/list_definition/list_definition.c @@ -0,0 +1,4 @@ +struct list { + int value; + struct list* next; +}; diff --git a/listings/chap10/main_ext/main_ext.c b/listings/chap10/main_ext/main_ext.c new file mode 100755 index 0000000..ef4a4f7 --- /dev/null +++ b/listings/chap10/main_ext/main_ext.c @@ -0,0 +1,7 @@ +int z = 0; +int square( int x ); + +int main(void) { + printf( "%d\n", square( 5 ) ); + return 0; +} diff --git a/listings/chap10/main_ldd/main_ldd.c b/listings/chap10/main_ldd/main_ldd.c new file mode 100755 index 0000000..88f4e47 --- /dev/null +++ b/listings/chap10/main_ldd/main_ldd.c @@ -0,0 +1,7 @@ +#include + +int main( void ) +{ + printf("Hello World!\n"); + return 0; +} diff --git a/listings/chap10/main_printer/main_printer.c b/listings/chap10/main_printer/main_printer.c new file mode 100755 index 0000000..278c8e5 --- /dev/null +++ b/listings/chap10/main_printer/main_printer.c @@ -0,0 +1,7 @@ +void print_one(void); +void print_two(void); +int main(void) { + print_one(); + print_two(); + return 0; +} diff --git a/listings/chap10/main_printer_new/main_printer_new.c b/listings/chap10/main_printer_new/main_printer_new.c new file mode 100755 index 0000000..c5405ba --- /dev/null +++ b/listings/chap10/main_printer_new/main_printer_new.c @@ -0,0 +1,7 @@ +#include "printer.h" + +int main(void) { + print_one(); + print_two(); + return 0; +} diff --git a/listings/chap10/main_square/main_square b/listings/chap10/main_square/main_square new file mode 100755 index 0000000..3a735d9 --- /dev/null +++ b/listings/chap10/main_square/main_square @@ -0,0 +1,18 @@ +> gcc -c -std=c89 -pedantic -Wall main_square.c +> objdump -t main_square.o + +main.o: file format elf64-x86-64 + +SYMBOL TABLE: +0000000000000000 l df *ABS* 0000000000000000 main.c +0000000000000000 l d .text 0000000000000000 .text +0000000000000000 l d .data 0000000000000000 .data +0000000000000000 l d .bss 0000000000000000 .bss +0000000000000000 l d .note.GNU-stack +0000000000000000 .note.GNU-stack +0000000000000000 l d .eh_frame +0000000000000000 .eh_frame +0000000000000000 l d .comment +0000000000000000 .comment +0000000000000000 g F .text 000000000000001c main +0000000000000000 *UND* 0000000000000000 square diff --git a/listings/chap10/main_square/main_square.c b/listings/chap10/main_square/main_square.c new file mode 100755 index 0000000..8264d57 --- /dev/null +++ b/listings/chap10/main_square/main_square.c @@ -0,0 +1,7 @@ +#include +int square( int x ); + +int main(void) { + printf( "%d\n", square( 5 ) ); + return 0; +} diff --git a/listings/chap10/multiple_inner_includes/multiple_inner_includes.c b/listings/chap10/multiple_inner_includes/multiple_inner_includes.c new file mode 100755 index 0000000..c3b1e6d --- /dev/null +++ b/listings/chap10/multiple_inner_includes/multiple_inner_includes.c @@ -0,0 +1,15 @@ +# 1 "main.c" +# 1 "" +# 1 "" +# 1 "/usr/include/stdc-predef.h" 1 3 4 +# 1 "" 2 +# 1 "main.c" +# 1 "a.h" 1 +void a(void); +# 2 "main.c" 2 +# 1 "b.h" 1 +# 1 "a.h" 1 +void a(void); +# 2 "b.h" 2 +void b(void); +# 2 "main.c" 2 diff --git a/listings/chap10/mutually_recursive_structures/mutually_recursive_structures.c b/listings/chap10/mutually_recursive_structures/mutually_recursive_structures.c new file mode 100755 index 0000000..fd8144a --- /dev/null +++ b/listings/chap10/mutually_recursive_structures/mutually_recursive_structures.c @@ -0,0 +1,10 @@ +struct b; /* forward declaration */ +struct a { + int value; + struct b* next; +}; + +/* no need to forward declare struct a because it is already defined */ +struct b { + struct a* other; +}; diff --git a/listings/chap10/pair/pair.h b/listings/chap10/pair/pair.h new file mode 100755 index 0000000..66d42d3 --- /dev/null +++ b/listings/chap10/pair/pair.h @@ -0,0 +1,14 @@ +#ifndef _PAIR_H_ +#define _PAIR_H_ + +#include + +struct pair { + int x; + int y; +}; + +void pair_apply( struct pair* pair, void (*f)(struct pair) ); +void pair_tofile( struct pair* pair, FILE* file ); + +#endif diff --git a/listings/chap10/printer/printer.c b/listings/chap10/printer/printer.c new file mode 100755 index 0000000..09014ac --- /dev/null +++ b/listings/chap10/printer/printer.c @@ -0,0 +1,8 @@ +#include + +void print_one(void) { + puts( "One" ); +} +void print_two(void) { + puts( "Two" ); +} diff --git a/listings/chap10/printer/printer.h b/listings/chap10/printer/printer.h new file mode 100755 index 0000000..f31ba55 --- /dev/null +++ b/listings/chap10/printer/printer.h @@ -0,0 +1,2 @@ +void print_one( void ); +void print_two( void ); diff --git a/listings/chap10/printf_check_header/printf_check_header b/listings/chap10/printf_check_header/printf_check_header new file mode 100755 index 0000000..d2fbcb3 --- /dev/null +++ b/listings/chap10/printf_check_header/printf_check_header @@ -0,0 +1,5 @@ +> cat p.c +#include + +> gcc -E -pedantic -ansi p.c | grep " printf" +extern int printf (const char *__restrict __format, ...); diff --git a/listings/chap10/printf_lib_entry/printf_lib_entry b/listings/chap10/printf_lib_entry/printf_lib_entry new file mode 100755 index 0000000..6f603dc --- /dev/null +++ b/listings/chap10/printf_lib_entry/printf_lib_entry @@ -0,0 +1,7 @@ +> readelf -s /lib/x86_64-linux-gnu/libc.so.6 | grep " printf" +596: 0000000000050d50 161 FUNC GLOBAL DEFAULT 12 +printf@@GLIBC_2.2.5 +1482: 0000000000050ca0 31 FUNC GLOBAL DEFAULT 12 +printf_size_info@@GLIBC_2.2.5 +1890: 0000000000050480 2070 FUNC GLOBAL DEFAULT 12 +printf_size@@GLIBC_2.2.5 diff --git a/listings/chap10/simple_malloc/simple_malloc.c b/listings/chap10/simple_malloc/simple_malloc.c new file mode 100755 index 0000000..eb8fbef --- /dev/null +++ b/listings/chap10/simple_malloc/simple_malloc.c @@ -0,0 +1,17 @@ +#include + + +int main( void ) { + int* array; + + /* malloc returns the allocated memory starting address + * Notice that its argument is the byte size, elements count multiplied + * by element size */ + array = malloc( 10 * sizeof( int )); + + /* actions on array are performed here */ + + free( array ); /* now the related memory region is deallocated */ + return 0; +} + diff --git a/listings/chap10/square/square b/listings/chap10/square/square new file mode 100755 index 0000000..a472c2b --- /dev/null +++ b/listings/chap10/square/square @@ -0,0 +1,16 @@ +> gcc -c -std=c89 -pedantic -Wall square.c +> objdump -t square.o +square.o: file format elf64-x86-64 + +SYMBOL TABLE: +0000000000000000 l df *ABS* 0000000000000000 square.c +0000000000000000 l d .text 0000000000000000 .text +0000000000000000 l d .data 0000000000000000 .data +0000000000000000 l d .bss 0000000000000000 .bss +0000000000000000 l d .note.GNU-stack +0000000000000000 .note.GNU-stack +0000000000000000 l d .eh_frame +0000000000000000 .eh_frame +0000000000000000 l d .comment +0000000000000000 .comment +0000000000000000 g F .text 0000000000000010 square diff --git a/listings/chap10/square/square.c b/listings/chap10/square/square.c new file mode 100755 index 0000000..0638c29 --- /dev/null +++ b/listings/chap10/square/square.c @@ -0,0 +1,2 @@ +int square( int x ) { return x * x; } + diff --git a/listings/chap10/square_ext/square_ext.c b/listings/chap10/square_ext/square_ext.c new file mode 100755 index 0000000..f9977b1 --- /dev/null +++ b/listings/chap10/square_ext/square_ext.c @@ -0,0 +1,2 @@ +extern int z; +int square( int x ) { return x * x + z; } diff --git a/listings/chap10/static_example/static_example.c b/listings/chap10/static_example/static_example.c new file mode 100755 index 0000000..0eeff28 --- /dev/null +++ b/listings/chap10/static_example/static_example.c @@ -0,0 +1,11 @@ +int global_int; +static int module_int; + +static int module_function() { + static int static_local_var; + int local_var; + return 0; +} +int main( int argc, char** argv ) { + return 0; +} diff --git a/listings/chap10/static_loc_var_example/static_loc_var_example.c b/listings/chap10/static_loc_var_example/static_loc_var_example.c new file mode 100755 index 0000000..6143617 --- /dev/null +++ b/listings/chap10/static_loc_var_example/static_loc_var_example.c @@ -0,0 +1,12 @@ +int demo (void) +{ + static int a = 42; + printf("%d\n", a++); +} + +... + +demo(); //outputs 42 +demo(); //outputs 43 +demo(); //outputs 44 + diff --git a/listings/chap10/struct_mutual_recursive_bad/struct_mutual_recursive_bad.c b/listings/chap10/struct_mutual_recursive_bad/struct_mutual_recursive_bad.c new file mode 100755 index 0000000..34ed80f --- /dev/null +++ b/listings/chap10/struct_mutual_recursive_bad/struct_mutual_recursive_bad.c @@ -0,0 +1,6 @@ +struct a { + struct b* foo; +}; +struct b { + struct a* bar; +}; diff --git a/listings/chap10/sum_malloc/sum_malloc.c b/listings/chap10/sum_malloc/sum_malloc.c new file mode 100755 index 0000000..769e780 --- /dev/null +++ b/listings/chap10/sum_malloc/sum_malloc.c @@ -0,0 +1,45 @@ +#include +#include + +int* array_read( size_t* out_count ) { + int* array; + size_t i; + size_t cnt; + scanf( "%zu", &cnt ); + array = malloc( cnt * sizeof( int ) ); + + for( i = 0; i < cnt; i++ ) + scanf( "%d", & array[i] ); + + *out_count = cnt; + return array; +} + +void array_print( int const* array, size_t count ) { + size_t i; + + for( i = 0; i < count; i++ ) + printf( "%d ", array[i] ); + puts(""); +} + +int array_sum( int const* array, size_t count ) { + size_t i; + int sum = 0; + for( i = 0; i < count; i++ ) + sum = sum + array[i]; + return sum; +} + +int main( void ) { + int* array; + size_t count; + + array = array_read( &count ); + array_print( array, count ); + printf( "Sum is: %d\n", array_sum( array, count ) ); + + free( array ); + + return 0; +} diff --git a/listings/chap11/.c b/listings/chap11/.c new file mode 100755 index 0000000..bd12021 --- /dev/null +++ b/listings/chap11/.c @@ -0,0 +1,3 @@ +char* best_guitar_solo = "Firth of fifth"; +char* good_genesis_song = "Firth of fifth"; +char* best_1973_live = "Firth of fifth"; diff --git a/listings/chap11/complex_decl_1/complex_decl_1.c b/listings/chap11/complex_decl_1/complex_decl_1.c new file mode 100755 index 0000000..6f24ef4 --- /dev/null +++ b/listings/chap11/complex_decl_1/complex_decl_1.c @@ -0,0 +1 @@ +int* (* (*fp) (int) ) [10]; diff --git a/listings/chap11/deref_ex/deref_ex.c b/listings/chap11/deref_ex/deref_ex.c new file mode 100755 index 0000000..7b6e354 --- /dev/null +++ b/listings/chap11/deref_ex/deref_ex.c @@ -0,0 +1,3 @@ +int catsAreCool = 0; +int* ptr = &catsAreCool; +*ptr = 1; /* catsAreCool = 1 */ diff --git a/listings/chap11/file_example/file_example.c b/listings/chap11/file_example/file_example.c new file mode 100755 index 0000000..52a258e --- /dev/null +++ b/listings/chap11/file_example/file_example.c @@ -0,0 +1,12 @@ +int smth[]={1,2,3,4,5}; +FILE* f = fopen( "hello.img", "rwb" ); + +fread( smth, sizeof(int), 1, f); + +/* This line is optional. By means of `fseek` function we can + navigate the file */ +fseek( f, 0, SEEK_SET ); + +fwrite(smth, 5 * sizeof( int ), 1, f); +fclose( f ); + diff --git a/listings/chap11/flex_array/flex_array.c b/listings/chap11/flex_array/flex_array.c new file mode 100755 index 0000000..c8b0e9d --- /dev/null +++ b/listings/chap11/flex_array/flex_array.c @@ -0,0 +1,17 @@ +#include +#include + +struct int_array { + size_t size; + int array[]; +}; + +struct int_array* array_create( size_t size ) { + struct int_array* array = malloc( + sizeof( *array ) + + sizeof( int ) * size ); + array-> size = size; + memset( array->array, 0, size ); + return array; +} + diff --git a/listings/chap11/flex_array_def/flex_array_def.c b/listings/chap11/flex_array_def/flex_array_def.c new file mode 100755 index 0000000..ab815a6 --- /dev/null +++ b/listings/chap11/flex_array_def/flex_array_def.c @@ -0,0 +1,4 @@ +struct char_array { + size_t length; + char data[]; +}; diff --git a/listings/chap11/fun_ptr_example/fun_ptr_example.c b/listings/chap11/fun_ptr_example/fun_ptr_example.c new file mode 100755 index 0000000..54998db --- /dev/null +++ b/listings/chap11/fun_ptr_example/fun_ptr_example.c @@ -0,0 +1,6 @@ +double doubler (int a) { return a * 2.5; } +... +double (*fptr)( int ); +double a; +fptr = &doubler; +a = fptr(10); /* a = 25.0 */ diff --git a/listings/chap11/fun_ptr_example_typedef/fun_ptr_example_typedef.c b/listings/chap11/fun_ptr_example_typedef/fun_ptr_example_typedef.c new file mode 100755 index 0000000..a999981 --- /dev/null +++ b/listings/chap11/fun_ptr_example_typedef/fun_ptr_example_typedef.c @@ -0,0 +1,7 @@ +double doubler (int a) { return a * 2.5; } +typedef double (megapointer_type)( int ); + +... +double a; +megapointer_type* variable = &doubler; +a = variable(10); /* a = 25.0 */ diff --git a/listings/chap11/inttypes/inttypes.c b/listings/chap11/inttypes/inttypes.c new file mode 100755 index 0000000..4931300 --- /dev/null +++ b/listings/chap11/inttypes/inttypes.c @@ -0,0 +1,10 @@ +#include +#include + +void f( void ) { + int64_t i64 = -10; + uint64_t u64 = 100; + printf( "Signed 64-bit integer: %" PRIi64 "\n", i64 ); + printf( "Unsigned 64-bit integer: %" PRIu64 "\n", u64 ); +} + diff --git a/listings/chap11/malloc_cast_explicit/malloc_cast_explicit.c b/listings/chap11/malloc_cast_explicit/malloc_cast_explicit.c new file mode 100755 index 0000000..322b003 --- /dev/null +++ b/listings/chap11/malloc_cast_explicit/malloc_cast_explicit.c @@ -0,0 +1 @@ +int* arr = (int*)malloc( sizeof(int) * 42 ); diff --git a/listings/chap11/malloc_no_cast/malloc_no_cast.c b/listings/chap11/malloc_no_cast/malloc_no_cast.c new file mode 100755 index 0000000..0ac8809 --- /dev/null +++ b/listings/chap11/malloc_no_cast/malloc_no_cast.c @@ -0,0 +1,5 @@ +#include +... +int* a = malloc(200); + +a[4] = 2; diff --git a/listings/chap11/null_check/null_check.c b/listings/chap11/null_check/null_check.c new file mode 100755 index 0000000..c453357 --- /dev/null +++ b/listings/chap11/null_check/null_check.c @@ -0,0 +1,6 @@ +if( x ) { ... } +if( NULL != x ) { ... } +if( 0 != x ) { ... } + +if( x != NULL ) { ... } +if( x != 0 ) { ... } diff --git a/listings/chap11/pointers_ex/pointers_ex.c b/listings/chap11/pointers_ex/pointers_ex.c new file mode 100755 index 0000000..65f719c --- /dev/null +++ b/listings/chap11/pointers_ex/pointers_ex.c @@ -0,0 +1,3 @@ +int a = 4; +int* p_a = &a; +*p_a = 10; /* a = 10*/ diff --git a/listings/chap11/ptr_change_ex/ptr_change_ex.c b/listings/chap11/ptr_change_ex/ptr_change_ex.c new file mode 100755 index 0000000..6d64120 --- /dev/null +++ b/listings/chap11/ptr_change_ex/ptr_change_ex.c @@ -0,0 +1,5 @@ +int a = 42; /* Assume this integer's address is 1000 */ +int* p_a = &a; +p_a += 42; /* 1000 + 42 * sizeof( int ) */ +p_a = p_a + 1; /* 1168 + 1 * sizeof( int ) */ +p_a --; /* 1172 - 1 * sizeof( int ) */ diff --git a/listings/chap11/ptr_diff_calc/ptr_diff_calc.c b/listings/chap11/ptr_diff_calc/ptr_diff_calc.c new file mode 100755 index 0000000..3312bac --- /dev/null +++ b/listings/chap11/ptr_diff_calc/ptr_diff_calc.c @@ -0,0 +1,4 @@ +int arr[128]; +int* ptr1 = &arr[50]; /* `array` address + 50 int sizes */ +int* ptr2 = &arr[90]; /* `array` address + 90 int sizes */ +ptrdiff_t d = ptr2 - ptr1; /* exactly 40 */ diff --git a/listings/chap11/ptr_mult_decl/ptr_mult_decl.c b/listings/chap11/ptr_mult_decl/ptr_mult_decl.c new file mode 100755 index 0000000..f997214 --- /dev/null +++ b/listings/chap11/ptr_mult_decl/ptr_mult_decl.c @@ -0,0 +1 @@ +int* a, *b, c; diff --git a/listings/chap11/ptrdiff_bug/ptrdiff_bug.c b/listings/chap11/ptrdiff_bug/ptrdiff_bug.c new file mode 100755 index 0000000..9fc5a05 --- /dev/null +++ b/listings/chap11/ptrdiff_bug/ptrdiff_bug.c @@ -0,0 +1,10 @@ +int* max; +int* cur; + +int f( unsigned int e ) +{ + if ( max - cur > e ) + return 1; + else + return 0; +} diff --git a/listings/chap11/str_glob/str_glob.c b/listings/chap11/str_glob/str_glob.c new file mode 100755 index 0000000..fb0ce30 --- /dev/null +++ b/listings/chap11/str_glob/str_glob.c @@ -0,0 +1,2 @@ +char str[] = "something_global"; +void f (void) { ... } diff --git a/listings/chap11/str_intern/str_intern.c b/listings/chap11/str_intern/str_intern.c new file mode 100755 index 0000000..bd12021 --- /dev/null +++ b/listings/chap11/str_intern/str_intern.c @@ -0,0 +1,3 @@ +char* best_guitar_solo = "Firth of fifth"; +char* good_genesis_song = "Firth of fifth"; +char* best_1973_live = "Firth of fifth"; diff --git a/listings/chap11/str_lit_example/str_lit_example.c b/listings/chap11/str_lit_example/str_lit_example.c new file mode 100755 index 0000000..88ee88b --- /dev/null +++ b/listings/chap11/str_lit_example/str_lit_example.c @@ -0,0 +1 @@ +char* str = "when the music is over, turn out the lights"; diff --git a/listings/chap11/str_lit_ptr_ex/str_lit_ptr_ex.c b/listings/chap11/str_lit_ptr_ex/str_lit_ptr_ex.c new file mode 100755 index 0000000..739acd9 --- /dev/null +++ b/listings/chap11/str_lit_ptr_ex/str_lit_ptr_ex.c @@ -0,0 +1,2 @@ +char will_be_o = "hello, world!"[4]; /* is 'o' */ +char const* tail = "abcde"+3 ; /* is "de", skipping 3 symbols */ diff --git a/listings/chap11/str_loc/str_loc.c b/listings/chap11/str_loc/str_loc.c new file mode 100755 index 0000000..cc726dd --- /dev/null +++ b/listings/chap11/str_loc/str_loc.c @@ -0,0 +1,3 @@ +void func(void) { + char str[] = "something_local"; +} diff --git a/listings/chap11/str_malloc/str_malloc.c b/listings/chap11/str_malloc/str_malloc.c new file mode 100755 index 0000000..0349eb4 --- /dev/null +++ b/listings/chap11/str_malloc/str_malloc.c @@ -0,0 +1,10 @@ +#include +#include + +int main( int argc, char** argv ) +{ + char* str = (char*)malloc( 25 ); + strcpy( str, "wow, such a nice string!" ); + + free( str ); +} diff --git a/listings/chap11/string_literal_mut/string_literal_mut.c b/listings/chap11/string_literal_mut/string_literal_mut.c new file mode 100755 index 0000000..2fdb6e4 --- /dev/null +++ b/listings/chap11/string_literal_mut/string_literal_mut.c @@ -0,0 +1,3 @@ +char* str = "hello world abcdefghijkl"; +/* the following line produces a runtime error */ +str[15] = '\''; diff --git a/listings/chap11/void_ptr_ex/void_ptr_ex.c b/listings/chap11/void_ptr_ex/void_ptr_ex.c new file mode 100755 index 0000000..0d972e1 --- /dev/null +++ b/listings/chap11/void_ptr_ex/void_ptr_ex.c @@ -0,0 +1,5 @@ +void* a = (void*)4; +short* b = (short*) a; +b ++; /* correct, b = 6 */ +b = a; /* correct */ +a = b; /* correct */ diff --git a/listings/chap12/align_str_ex1/align_str_ex1 b/listings/chap12/align_str_ex1/align_str_ex1 new file mode 100755 index 0000000..dbd8379 --- /dev/null +++ b/listings/chap12/align_str_ex1/align_str_ex1 @@ -0,0 +1,4 @@ +struct mystr { + uint16_t a; + uint64_t b; +}; diff --git a/listings/chap12/align_str_read/align_str_read.c b/listings/chap12/align_str_read/align_str_read.c new file mode 100755 index 0000000..7e58632 --- /dev/null +++ b/listings/chap12/align_str_read/align_str_read.c @@ -0,0 +1,6 @@ +struct str { + uint16_t a; /* a gap of 4 bytes */ + uint64_t b; +}; +struct str mystr; +fread( &mystr, sizeof( str ), 1, f ); diff --git a/listings/chap12/alignas_ex/alignas_ex.c b/listings/chap12/alignas_ex/alignas_ex.c new file mode 100755 index 0000000..8e871b3 --- /dev/null +++ b/listings/chap12/alignas_ex/alignas_ex.c @@ -0,0 +1,8 @@ +#include +#include + +int main( void ) { + alignas( 8 ) short x; + printf( "%zu\n", alignof( x ) ); + return 0; +} diff --git a/listings/chap12/alignof_ex/alignof_ex.c b/listings/chap12/alignof_ex/alignof_ex.c new file mode 100755 index 0000000..26ab492 --- /dev/null +++ b/listings/chap12/alignof_ex/alignof_ex.c @@ -0,0 +1,8 @@ +#include +#include + +int main(void) { + short x; + printf("%zu\n", alignof(x)); + return 0; +} diff --git a/listings/chap12/grammar_nat_pm/grammar_nat_pm b/listings/chap12/grammar_nat_pm/grammar_nat_pm new file mode 100755 index 0000000..0e75f25 --- /dev/null +++ b/listings/chap12/grammar_nat_pm/grammar_nat_pm @@ -0,0 +1,6 @@ + ::= '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' + ::= '0' | + ::= | + ::= | + + ::= | '+' | '-' diff --git a/listings/chap12/grammar_nat_pm_mult/grammar_nat_pm_mult b/listings/chap12/grammar_nat_pm_mult/grammar_nat_pm_mult new file mode 100755 index 0000000..18173c6 --- /dev/null +++ b/listings/chap12/grammar_nat_pm_mult/grammar_nat_pm_mult @@ -0,0 +1,8 @@ + ::= '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' + ::= '0' | + ::= | + ::= | + + ::= | '+' + | '-' | '*' + diff --git a/listings/chap12/grammar_naturals/grammar_naturals b/listings/chap12/grammar_naturals/grammar_naturals new file mode 100755 index 0000000..c9c165b --- /dev/null +++ b/listings/chap12/grammar_naturals/grammar_naturals @@ -0,0 +1,4 @@ + ::= '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' + ::= '0' | + ::= | + ::= | diff --git a/listings/chap12/grammar_naturals_nullterm/grammar_naturals_nullterm b/listings/chap12/grammar_naturals_nullterm/grammar_naturals_nullterm new file mode 100755 index 0000000..1637cc2 --- /dev/null +++ b/listings/chap12/grammar_naturals_nullterm/grammar_naturals_nullterm @@ -0,0 +1,5 @@ + ::= '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' + ::= '0' | + ::= | + ::= | + ::= '\0' diff --git a/listings/chap12/grammar_priorities/grammar_priorities b/listings/chap12/grammar_priorities/grammar_priorities new file mode 100755 index 0000000..927d011 --- /dev/null +++ b/listings/chap12/grammar_priorities/grammar_priorities @@ -0,0 +1,5 @@ + ::= 0 "<" | 0 "<=" + | 0 "==" | 0 ">" | 0 ">=" | 0 +0 = 1 "+" | 1 "-" | 1 +1 ::= "*" 1 | "/" 1 | + ::= "(" ")" | diff --git a/listings/chap12/imp/imp b/listings/chap12/imp/imp new file mode 100755 index 0000000..d7d63cb --- /dev/null +++ b/listings/chap12/imp/imp @@ -0,0 +1,12 @@ + ::= | ";" + ::= "{" "}" | | | | + ::= "" "(" ")" + ::= IDENT "=" + ::= "" "(" ")" "" + ::= "" "(" ")" + + ::= "<" | "<=" + | "==" | ">" | ">=" | + = "+" | "-" | + ::= "*" | "/" | + ::= "(" ")" | NUMBER diff --git a/listings/chap12/pack_2/pack_2.c b/listings/chap12/pack_2/pack_2.c new file mode 100755 index 0000000..cd1a540 --- /dev/null +++ b/listings/chap12/pack_2/pack_2.c @@ -0,0 +1,6 @@ +#pragma pack(push, 2) +struct mystr { + uint16_t a; + int64_t b; +}; +#pragma pack(pop) diff --git a/listings/chap12/pack_4/pack_4.c b/listings/chap12/pack_4/pack_4.c new file mode 100755 index 0000000..dcc32ac --- /dev/null +++ b/listings/chap12/pack_4/pack_4.c @@ -0,0 +1,6 @@ +#pragma pack(push, 4) +struct mystr { + uint16_t a; + int64_t b; +}; +#pragma pack(pop) diff --git a/listings/chap12/pragma_pack/pragma_pack.c b/listings/chap12/pragma_pack/pragma_pack.c new file mode 100755 index 0000000..7cb03f4 --- /dev/null +++ b/listings/chap12/pragma_pack/pragma_pack.c @@ -0,0 +1,6 @@ +#pragma pack(push, 2) +struct mystr { + short a; + long b; +}; +#pragma pack(pop) diff --git a/listings/chap12/ptr_analysis1/ptr_analysis1.c b/listings/chap12/ptr_analysis1/ptr_analysis1.c new file mode 100755 index 0000000..cd810e9 --- /dev/null +++ b/listings/chap12/ptr_analysis1/ptr_analysis1.c @@ -0,0 +1,6 @@ +int x = 0; +int* p = &x; +... +/* there are no writes to `p` in these lines */ +... +*p = 10; /* this pointer can not be NULL */ diff --git a/listings/chap12/ptr_analysis2/ptr_analysis2.c b/listings/chap12/ptr_analysis2/ptr_analysis2.c new file mode 100755 index 0000000..67400d8 --- /dev/null +++ b/listings/chap12/ptr_analysis2/ptr_analysis2.c @@ -0,0 +1,8 @@ +int x = 0; +int* p = &x; +... +/* there are no writes to `p` in these lines */ +int** z = &p; +*z = NULL; /* Still not a direct write to `p` */ +... +*p = 10; /* this pointer can not be NULL */ diff --git a/listings/chap12/rec_desc_nat/rec_desc_nat.c b/listings/chap12/rec_desc_nat/rec_desc_nat.c new file mode 100755 index 0000000..868dbad --- /dev/null +++ b/listings/chap12/rec_desc_nat/rec_desc_nat.c @@ -0,0 +1,45 @@ +#include +#include + +char const* stream = NULL ; + +bool accept(char c) { + if (*stream == c) { + stream++; + return true; + } + else return false; +} +bool notzero( void ) { + return accept( '1' ) || accept( '2' ) || accept( '3' ) + || accept( '4' ) || accept( '5' ) || accept( '6' ) + || accept( '7' ) || accept( '8' ) || accept( '9' ); +} +bool digit( void ) { + return accept('0') || notzero(); +} +bool raw( void ) { + if ( digit() ) { raw(); return true; } + return false; +} +bool number( void ) { + if ( notzero() ) { + raw(); + return true; + } else return accept('0'); +} +bool str( void ) { + return number() && accept( 0 ); +} +void check( const char* string ) { + stream = string; + printf("%s -> %d\n", string, str() ); +} +int main(void) { + check("12345"); + check("hello12"); + check("0002"); + check("10dbd"); + check("0"); + return 0; +} diff --git a/listings/chap12/seq_points/seq_points.c b/listings/chap12/seq_points/seq_points.c new file mode 100755 index 0000000..e099ba2 --- /dev/null +++ b/listings/chap12/seq_points/seq_points.c @@ -0,0 +1,2 @@ +int i = 0; +i = i ++ * 10; diff --git a/listings/chap12/str_attribute_packed/str_attribute_packed.c b/listings/chap12/str_attribute_packed/str_attribute_packed.c new file mode 100755 index 0000000..d94a2d5 --- /dev/null +++ b/listings/chap12/str_attribute_packed/str_attribute_packed.c @@ -0,0 +1,5 @@ +struct __attribute__(( packed )) mystr { + uint8_t first; + float delta; + float position; +}; diff --git a/listings/chap13/assert/assert.c b/listings/chap13/assert/assert.c new file mode 100755 index 0000000..b1824bf --- /dev/null +++ b/listings/chap13/assert/assert.c @@ -0,0 +1,6 @@ +#include +int main() { + int x = 0; + assert( x != 0 ); + return 0; +} diff --git a/listings/chap13/bmp_struct/bmp_struct.c b/listings/chap13/bmp_struct/bmp_struct.c new file mode 100755 index 0000000..4dccdb1 --- /dev/null +++ b/listings/chap13/bmp_struct/bmp_struct.c @@ -0,0 +1,20 @@ +#include +struct __attribute__((packed)) + bmp_header { + uint16_t bfType; + uint32_t bfileSize; + uint32_t bfReserved; + uint32_t bOffBits; + uint32_t biSize; + + uint32_t biWidth; + uint32_t biHeight; + uint16_t biPlanes; + uint16_t biBitCount; + uint32_t biCompression; + uint32_t biSizeImage; + uint32_t biXPelsPerMeter; + uint32_t biYPelsPerMeter; + uint32_t biClrUsed; + uint32_t biClrImportant; + }; diff --git a/listings/chap13/div_cb/div_cb.c b/listings/chap13/div_cb/div_cb.c new file mode 100755 index 0000000..e482adc --- /dev/null +++ b/listings/chap13/div_cb/div_cb.c @@ -0,0 +1,21 @@ +#include + +int div( int x, int y, void (onerror)(int, int)) { + if ( y != 0 ) + return x/y; + else { + onerror(x,y); + return 0; + } +} + +static void div_by_zero(int x, int y) { + fprintf( stderr, "Division by zero: %d / %d\n", x, y ); +} + +int main(void) { + printf("%d %d\n", + div( 10, 2, div_by_zero ), + div( 10, 0, div_by_zero ) ); + return 0; +} diff --git a/listings/chap13/doxygen_example/doxygen_example.h b/listings/chap13/doxygen_example/doxygen_example.h new file mode 100755 index 0000000..dd2a33b --- /dev/null +++ b/listings/chap13/doxygen_example/doxygen_example.h @@ -0,0 +1,30 @@ +#pragma once +#include +#include + +/** @defgroup const_pool Constant pool */ + +/** Free allocated memory for the pool contents +*/ +void const_pool_deinit( struct vm_const_pool* pool ); + +/** Non-destructive constant pool combination + * @param a First pool. + * @param b Second pool. + * @returns An initialized constant pool combining contents of both arguments + */ +struct vm_const_pool const_combine( + struct vm_const_pool const* a, + struct vm_const_pool const* b ); + + +/** Change the constant pool by adding the other pool's contents in its end. + * @param[out] src The source pool which will be modified. + * @param fresh The pool to merge with the `src` pool. + */ +void const_merge( + struct vm_const_pool* src, + struct vm_const_pool const* fresh ); + +/**@} */ + diff --git a/listings/chap13/dump_1/dump_1.c b/listings/chap13/dump_1/dump_1.c new file mode 100755 index 0000000..86e743d --- /dev/null +++ b/listings/chap13/dump_1/dump_1.c @@ -0,0 +1,5 @@ +void dump( char const* filename ) { + FILE* f = fopen( filename, "w" ); + fprintf(f, "this is the dump %d", 42 ); + fclose( f ); +} diff --git a/listings/chap13/dump_2/dump_2.c b/listings/chap13/dump_2/dump_2.c new file mode 100755 index 0000000..7215170 --- /dev/null +++ b/listings/chap13/dump_2/dump_2.c @@ -0,0 +1,8 @@ +void dump( FILE* f ) { + fprintf(f, "this is the dump %d", 42 ); +} +void fun( void ) { + FILE* f = fopen( "dump.txt", "w" ); + dump( f ); + fclose( f ); +} diff --git a/listings/chap13/enum_ex/enum_ex.c b/listings/chap13/enum_ex/enum_ex.c new file mode 100755 index 0000000..fdcd2b2 --- /dev/null +++ b/listings/chap13/enum_ex/enum_ex.c @@ -0,0 +1,5 @@ +enum exit_code { + EX_SUCCESS, + EX_FAILURE, + EX_INVALID_ARGUMENTS +}; diff --git a/listings/chap13/err_switch_arr/err_switch_arr.c b/listings/chap13/err_switch_arr/err_switch_arr.c new file mode 100755 index 0000000..a43e1d8 --- /dev/null +++ b/listings/chap13/err_switch_arr/err_switch_arr.c @@ -0,0 +1,21 @@ +enum error_code { + ERROR1, + ERROR2 +}; +... +enum error_code err; +... +switch (err) { + case ERROR1: ... break; + case ERROR2: ... break; + default: ... break; +} + +/* alternatively */ + +static const char* const messages[] = { + "It is the first error\n", + "The second error it is\n" +}; + +fprintf( stderr, messages[err] ); diff --git a/listings/chap13/error_code/error_code.c b/listings/chap13/error_code/error_code.c new file mode 100755 index 0000000..2ed8d11 --- /dev/null +++ b/listings/chap13/error_code/error_code.c @@ -0,0 +1,9 @@ +enum div_res { + DIV_OK, + DIV_BYZERO +}; + +enum div_res div( int x, int y, int* result ) { + if ( y != 0 ) { *result = x/y; return DIV_OK; } + else return DIV_BYZERO; +} diff --git a/listings/chap13/file_open_sep/file_open_sep.c b/listings/chap13/file_open_sep/file_open_sep.c new file mode 100755 index 0000000..0627f6b --- /dev/null +++ b/listings/chap13/file_open_sep/file_open_sep.c @@ -0,0 +1,28 @@ +#include + +enum stat { + STAT_OK, + STAT_ERR_OPEN, + STAT_ERR_CLOSE, + STAT_ERR_WRITE +}; + +enum stat dump( FILE * f ) { + if ( fprintf( f, "this is the dump %d", 42 ) ) return STAT_OK; + return STAT_ERR_WRITE; +} + +enum stat fun( void ) { + enum stat dump_stat; + FILE * f; + + f = fopen( "dump.txt", "w" ); + if (!f) return STAT_ERR_OPEN; + + dump_stat = dump( f ); + + if ( dump_stat != STAT_OK ) return dump_stat; + if (! fclose( f ) ) return STAT_ERR_CLOSE; + + return STAT_OK; +} diff --git a/listings/chap13/goto_error_recover/goto_error_recover.c b/listings/chap13/goto_error_recover/goto_error_recover.c new file mode 100755 index 0000000..49d6fc2 --- /dev/null +++ b/listings/chap13/goto_error_recover/goto_error_recover.c @@ -0,0 +1,16 @@ +void foo(void) +{ + if (!doA()) goto exit; + if (!doB()) goto revertA; + if (!doC()) goto revertB; + + /* doA, doB and doC succeeded */ + return; + +revertB: + undoB(); +revertA: + undoA(); +exit: + return; +} diff --git a/listings/chap13/image_rot_stub/image_rot_stub.c b/listings/chap13/image_rot_stub/image_rot_stub.c new file mode 100755 index 0000000..4a537ac --- /dev/null +++ b/listings/chap13/image_rot_stub/image_rot_stub.c @@ -0,0 +1,38 @@ +#include +#include + +struct pixel { uint8_t b,g,r; }; + +struct image { + uint64_t width, height; + struct pixel_t* data; +}; + +/* deserializer */ +enum read_status { + READ_OK = 0, + READ_INVALID_SIGNATURE, + READ_INVALID_BITS, + READ_INVALID_HEADER + /* more codes */ +}; + +enum read_status from_bmp( FILE* in, struct image* const read ); + +/* image_t from_jpg( FILE* );... + * and other deserializers are possible + * All information needed will be + * stored in image structure */ + +/* makes a rotated copy */ +struct image rotate( struct image const source ); + + +/* serializer */ +enum write_status { + WRITE_OK = 0, + WRITE_ERROR + /* more codes */ +}; + +enum write_status to_bmp( FILE* out, struct image const* img ); diff --git a/listings/chap13/list_sum_bad/list_sum_bad.c b/listings/chap13/list_sum_bad/list_sum_bad.c new file mode 100755 index 0000000..9e0ce11 --- /dev/null +++ b/listings/chap13/list_sum_bad/list_sum_bad.c @@ -0,0 +1,10 @@ +int list_sum( const struct list* l ) { + size_t i; + int sum = 0; + /* We do not want to launch the full computation + * of size at each cycle iteration */ + size_t sz = list_size( l ) ; + for( i = 0; i < sz; l = l-> next ) + sum = sum + l->value; + return sum; +} diff --git a/listings/chap13/mem/mem.h b/listings/chap13/mem/mem.h new file mode 100755 index 0000000..638f2df --- /dev/null +++ b/listings/chap13/mem/mem.h @@ -0,0 +1,36 @@ +#ifndef _MEM_H_ +#define _MEM_H_ + +#define __USE_MISC + +#include +#include +#include + +#include + +#define HEAP_START ((void*)0x04040000) + +struct mem; + +#pragma pack(push, 1) +struct mem { + struct mem* next; + size_t capacity; + bool is_free; +}; +#pragma pack(pop) + +void* _malloc( size_t query ); +void _free( void* mem ); +void* heap_init( size_t initial_size ); + +#define DEBUG_FIRST_BYTES 4 + + +void memalloc_debug_struct_info( FILE* f, + struct mem const* const address ); + +void memalloc_debug_heap( FILE* f, struct mem const* ptr ); + +#endif diff --git a/listings/chap13/mem_debug/mem_debug.c b/listings/chap13/mem_debug/mem_debug.c new file mode 100755 index 0000000..11e68bc --- /dev/null +++ b/listings/chap13/mem_debug/mem_debug.c @@ -0,0 +1,23 @@ +#include "mem.h" + +void memalloc_debug_struct_info( FILE* f, + struct mem const* const address ) { + + size_t i; + fprintf( f, + "start: %p\nsize: %lu\nis_free: %d\n", + (void*)address, + address-> capacity, + address-> is_free ); + for ( i = 0; + i < DEBUG_FIRST_BYTES && i < address-> capacity; + ++i ) + fprintf( f, "%hhX", + ((char*)address)[ sizeof( struct mem_t ) + i ] ); + putc( '\n', f ); +} + +void memalloc_debug_heap( FILE* f, struct mem const* ptr ) { + for( ; ptr; ptr = ptr->next ) + memalloc_debug_struct_info( f, ptr ); +} diff --git a/listings/chap13/mem_str/mem_str.c b/listings/chap13/mem_str/mem_str.c new file mode 100755 index 0000000..78fd63a --- /dev/null +++ b/listings/chap13/mem_str/mem_str.c @@ -0,0 +1,5 @@ +struct mem { + struct mem* next; + size_t capacity; + bool is_free; +}; diff --git a/listings/chap13/pixel/pixel.c b/listings/chap13/pixel/pixel.c new file mode 100755 index 0000000..6bcbe14 --- /dev/null +++ b/listings/chap13/pixel/pixel.c @@ -0,0 +1,3 @@ +struct pixel { + unsigned char b, g, r; +} diff --git a/listings/chap13/reenterability/reenterability.c b/listings/chap13/reenterability/reenterability.c new file mode 100755 index 0000000..035d387 --- /dev/null +++ b/listings/chap13/reenterability/reenterability.c @@ -0,0 +1,9 @@ +bool flag = true; +int var = 0; +void g(void) { + f(); + flag = false; +} +void f(void) { + if (flag) g(); +} diff --git a/listings/chap13/stack/stack.c b/listings/chap13/stack/stack.c new file mode 100755 index 0000000..2e6fbf0 --- /dev/null +++ b/listings/chap13/stack/stack.c @@ -0,0 +1,55 @@ +#include +#include "stack.h" + +struct list { int value; struct list* next; }; + +static struct list* list_new( int item, struct list* next ) { + struct list* lst = malloc( sizeof( *lst ) ); + lst->value = item; + lst->next = next; + return lst; +} + +void stack_push( struct stack* s, int value ) { + s->first = list_new( value, s->first ); + if ( s->last == NULL ) s->last = s-> first; + s->count++; +} + +int stack_pop( struct stack* s ) { + struct list* const head = s->first; + int value; + if ( head ) { + if ( head->next ) s->first = head->next; + value = head->value; + free( head ); + if( -- s->count ) { + s->first = s->last = NULL; + } + return value; + } + return 0; +} + +void stack_foreach( struct stack* s, void (f)(int) ) { + struct list* cur; + for( cur = s->first; cur; cur = cur-> next ) + f( cur->value ); + +} + +bool stack_is_empty( struct stack const* s ) { + return s->count == 0; +} + +struct stack stack_init( void ) { + struct stack empty = { NULL, NULL, 0 }; + return empty; +} + +void stack_deinit( struct stack* st ) { + while( ! stack_is_empty( st ) ) stack_pop( st ); + st-> first = NULL; + st-> last = NULL; +} + diff --git a/listings/chap13/stack/stack.h b/listings/chap13/stack/stack.h new file mode 100755 index 0000000..c6c4b2f --- /dev/null +++ b/listings/chap13/stack/stack.h @@ -0,0 +1,27 @@ +#ifndef _STACK_H_ +#define _STACK_H_ + +#include +#include +#include + + +struct list; + +struct stack { + struct list* first; + struct list* last; + size_t count; +}; + +struct stack stack_init ( void ); +void stack_deinit( struct stack* st ); + +void stack_push( struct stack* s, int value ); +int stack_pop ( struct stack* s ); +bool stack_is_empty( struct stack const* s ); + + +void stack_foreach( struct stack* s, void (f)(int) ); + +#endif /* _STACK_H_ */ diff --git a/listings/chap13/struct_private_ex/struct_private_ex.c b/listings/chap13/struct_private_ex/struct_private_ex.c new file mode 100755 index 0000000..0c5070d --- /dev/null +++ b/listings/chap13/struct_private_ex/struct_private_ex.c @@ -0,0 +1,5 @@ +struct mypair { + int x; + int y; + int _refcount; +}; diff --git a/listings/chap14/buffer_overrun/buffer_overrun.c b/listings/chap14/buffer_overrun/buffer_overrun.c new file mode 100755 index 0000000..5876363 --- /dev/null +++ b/listings/chap14/buffer_overrun/buffer_overrun.c @@ -0,0 +1,11 @@ +#include + +void f( void ) { + char buffer[16]; + gets( buffer ); +} + +int main( int argc, char** argv ) { + f(); + return 0; +} diff --git a/listings/chap14/epilogue/epilogue.asm b/listings/chap14/epilogue/epilogue.asm new file mode 100755 index 0000000..17b61fc --- /dev/null +++ b/listings/chap14/epilogue/epilogue.asm @@ -0,0 +1,3 @@ +mov rsp, rbp +pop rbp +ret diff --git a/listings/chap14/epilogue_alt/epilogue_alt.asm b/listings/chap14/epilogue_alt/epilogue_alt.asm new file mode 100755 index 0000000..ff09c6d --- /dev/null +++ b/listings/chap14/epilogue_alt/epilogue_alt.asm @@ -0,0 +1,2 @@ +leave +ret diff --git a/listings/chap14/gdb_printf/gdb_printf b/listings/chap14/gdb_printf/gdb_printf new file mode 100755 index 0000000..216c7da --- /dev/null +++ b/listings/chap14/gdb_printf/gdb_printf @@ -0,0 +1,4 @@ +(gdb) x/10 $rsp +0x7fffffffdfe0: 0x25207825 0x78252078 0x20782520 0x25207825 +0x7fffffffdff0: 0x78252078 0x20782520 0x25207825 0x00000078 +0x7fffffffe000: 0x00000000 0x00000000 diff --git a/listings/chap14/lma_bad/lma_bad.c b/listings/chap14/lma_bad/lma_bad.c new file mode 100755 index 0000000..a3a1fb3 --- /dev/null +++ b/listings/chap14/lma_bad/lma_bad.c @@ -0,0 +1,3 @@ +char* ptr; +for( ptr = start; ptr < start + size; ptr += pagesize ) +*ptr; diff --git a/listings/chap14/lma_good/lma_good.c b/listings/chap14/lma_good/lma_good.c new file mode 100755 index 0000000..84c0cd3 --- /dev/null +++ b/listings/chap14/lma_good/lma_good.c @@ -0,0 +1,3 @@ +volatile char* ptr; +for( ptr = start; ptr < start + size; ptr += pagesize ) +*ptr; diff --git a/listings/chap14/longjmp/longjmp.c b/listings/chap14/longjmp/longjmp.c new file mode 100755 index 0000000..0c3f480 --- /dev/null +++ b/listings/chap14/longjmp/longjmp.c @@ -0,0 +1,12 @@ +#include +#include + +int main(void) { + jmp_buf jb; + int val; + val = setjmp( jb ); + puts("Hello!"); + if (val == 0) longjmp( jb, 1 ); + else puts("End"); + return 0; +} diff --git a/listings/chap14/longjmp_ub/longjmp_ub.c b/listings/chap14/longjmp_ub/longjmp_ub.c new file mode 100755 index 0000000..b8aec84 --- /dev/null +++ b/listings/chap14/longjmp_ub/longjmp_ub.c @@ -0,0 +1,9 @@ +jmp_buf jb; +void f(void) { + setjmp( jb ); +} + +void g(void) { + f(); + longjmp(jb); +} diff --git a/listings/chap14/maximum/maximum.asm b/listings/chap14/maximum/maximum.asm new file mode 100755 index 0000000..1045a07 --- /dev/null +++ b/listings/chap14/maximum/maximum.asm @@ -0,0 +1,23 @@ +00000000004004b6 : +4004b6: 55 push rbp +4004b7: 48 89 e5 mov rbp,rsp +4004ba: 48 81 ec 90 0f 00 00 sub rsp,0xf90 +4004c1: 89 bd fc ef ff ff mov DWORD PTR [rbp-0x1004],edi +4004c7: 89 b5 f8 ef ff ff mov DWORD PTR [rbp-0x1008],esi +4004cd: 8b 85 fc ef ff ff mov eax,DWORD PTR [rbp-0x1004] +4004d3: 3b 85 f8 ef ff ff cmp eax,DWORD PTR [rbp-0x1008] +4004d9: 7d 08 jge 4004e3 +4004db: 8b 85 f8 ef ff ff mov eax,DWORD PTR [rbp-0x1008] +4004e1: eb 06 jmp 4004e9 +4004e3: 8b 85 fc ef ff ff mov eax,DWORD PTR [rbp-0x1004] +4004e9: c9 leave +4004ea: c3 ret + +00000000004004eb
: +4004eb: 55 push rbp +4004ec: 48 89 e5 mov rbp,rsp +4004ef: 48 83 ec 10 sub rsp,0x10 +4004f3: be e7 03 00 00 mov esi,0x3e7 +4004f8: bf 2a 00 00 00 mov edi,0x2a +4004fd: e8 b4 ff ff ff call 4004b6 +400502: 89 45 fc mov DWORD PTR [rbp-0x4],eax diff --git a/listings/chap14/maximum/maximum.c b/listings/chap14/maximum/maximum.c new file mode 100755 index 0000000..7b6b499 --- /dev/null +++ b/listings/chap14/maximum/maximum.c @@ -0,0 +1,11 @@ + +int maximum( int a, int b ) { + char buffer[4096]; + if (a < b) return b; + return a; +} + +int main(void) { + int x = maximum( 42, 999 ); + return 0; +} diff --git a/listings/chap14/maximum_refined/maximum_refined.asm b/listings/chap14/maximum_refined/maximum_refined.asm new file mode 100755 index 0000000..7d6cc31 --- /dev/null +++ b/listings/chap14/maximum_refined/maximum_refined.asm @@ -0,0 +1,16 @@ +mov rsi, 999 +mov rdi, 42 +call maximum +... +maximum: +push rbp +mov rbp, rsp +sub rsp, 3984 + +mov [rbp-0x1004], edi +mov [rbp-0x1008], esi +mov eax, [rbp-0x1004] +... + +leave +ret diff --git a/listings/chap14/printf_n/printf_n.c b/listings/chap14/printf_n/printf_n.c new file mode 100755 index 0000000..fa5eb13 --- /dev/null +++ b/listings/chap14/printf_n/printf_n.c @@ -0,0 +1,8 @@ +#include + +int main(void) { + int count; + printf( "hello%n world\n", &count); + printf( "%d\n", count ); + return 0; +} diff --git a/listings/chap14/printf_n_ex/printf_n_ex.c b/listings/chap14/printf_n_ex/printf_n_ex.c new file mode 100755 index 0000000..f8337ea --- /dev/null +++ b/listings/chap14/printf_n_ex/printf_n_ex.c @@ -0,0 +1,3 @@ +int x; +printf("%d %n", 10, &x); /* x = 3 */ +printf("%d %n", 200, &x); /* x = 4 */ diff --git a/listings/chap14/printf_vuln/printf_vuln.c b/listings/chap14/printf_vuln/printf_vuln.c new file mode 100755 index 0000000..4f158b8 --- /dev/null +++ b/listings/chap14/printf_vuln/printf_vuln.c @@ -0,0 +1,7 @@ +#include +int main(void) { + char buffer[1024]; + gets(buffer); + printf( buffer ); + return 0; +} diff --git a/listings/chap14/prologue/prologue.asm b/listings/chap14/prologue/prologue.asm new file mode 100755 index 0000000..2ee69a0 --- /dev/null +++ b/listings/chap14/prologue/prologue.asm @@ -0,0 +1,5 @@ +func: +push rbp +mov rbp, rsp + +sub rsp, 24 ; given 24 is total size of local variables diff --git a/listings/chap14/restrict-hack-dump/restrict-hack-dump b/listings/chap14/restrict-hack-dump/restrict-hack-dump new file mode 100755 index 0000000..ea502be --- /dev/null +++ b/listings/chap14/restrict-hack-dump/restrict-hack-dump @@ -0,0 +1,5 @@ +0000000000000000 : + 0: 8b 06 mov eax,DWORD PTR [rsi] + 2: 01 c0 add eax,eax + 4: 01 07 add DWORD PTR [rdi],eax + 6: c3 ret diff --git a/listings/chap14/restrict-hack/restrict-hack.c b/listings/chap14/restrict-hack/restrict-hack.c new file mode 100755 index 0000000..1bbdf6c --- /dev/null +++ b/listings/chap14/restrict-hack/restrict-hack.c @@ -0,0 +1,11 @@ +struct a { + int v; +}; +struct b { + int v; +}; + +void f(struct a* x, struct b* add) { + x->v += add->v; + x->v += add->v; +} diff --git a/listings/chap14/restrict_hierarchy/restrict_hierarchy.c b/listings/chap14/restrict_hierarchy/restrict_hierarchy.c new file mode 100755 index 0000000..b92efd6 --- /dev/null +++ b/listings/chap14/restrict_hierarchy/restrict_hierarchy.c @@ -0,0 +1,11 @@ +struct s { + int* x; +} inst; + +void f(void) { + struct s* restrict p_s = &inst; + int* restrict p_x = p_s->x; /* Bad */ + { + int* restrict p_x2 = p_s->x; /* Fine, other block scope */ + } +} diff --git a/listings/chap14/restrict_motiv/restrict_motiv.c b/listings/chap14/restrict_motiv/restrict_motiv.c new file mode 100755 index 0000000..69988e9 --- /dev/null +++ b/listings/chap14/restrict_motiv/restrict_motiv.c @@ -0,0 +1,4 @@ +void f(int* x, int* add) { + *x += *add; + *x += *add; +} diff --git a/listings/chap14/restrict_motiv1/restrict_motiv1.c b/listings/chap14/restrict_motiv1/restrict_motiv1.c new file mode 100755 index 0000000..365085d --- /dev/null +++ b/listings/chap14/restrict_motiv1/restrict_motiv1.c @@ -0,0 +1,4 @@ +void f(int* restrict x, int* restrict add) { + *x += *add; + *x += *add; +} diff --git a/listings/chap14/restrict_motiv_dump/restrict_motiv_dump.asm b/listings/chap14/restrict_motiv_dump/restrict_motiv_dump.asm new file mode 100755 index 0000000..1498a52 --- /dev/null +++ b/listings/chap14/restrict_motiv_dump/restrict_motiv_dump.asm @@ -0,0 +1,7 @@ +0000000000000000 : +0: 8b 06 mov eax,DWORD PTR [rsi] +2: 03 07 add eax,DWORD PTR [rdi] +4: 89 07 mov DWORD PTR [rdi],eax +6: 03 06 add eax,DWORD PTR [rsi] +8: 89 07 mov DWORD PTR [rdi],eax +a: c3 ret diff --git a/listings/chap14/restrict_motiv_dump1/restrict_motiv_dump1.asm b/listings/chap14/restrict_motiv_dump1/restrict_motiv_dump1.asm new file mode 100755 index 0000000..5e4be32 --- /dev/null +++ b/listings/chap14/restrict_motiv_dump1/restrict_motiv_dump1.asm @@ -0,0 +1,6 @@ +0000000000000000 : + 0: 8b 06 mov eax,DWORD PTR [rsi] + 2: 01 c0 add eax,eax + 4: 01 07 add DWORD PTR [rdi],eax + 6: c3 ret + diff --git a/listings/chap14/rz/rz.asm b/listings/chap14/rz/rz.asm new file mode 100755 index 0000000..7b4bb47 --- /dev/null +++ b/listings/chap14/rz/rz.asm @@ -0,0 +1,12 @@ +0000000000400546 : +400546: 55 push rbp +400547: 48 89 e5 mov rbp,rsp +40054a: 48 83 ec 70 sub rsp,0x70 +40054e: 64 48 8b 04 25 28 00 mov rax,QWORD PTR fs:0x28 +400555: 00 00 +400557: 48 89 45 f8 mov QWORD PTR [rbp-0x8],rax +40055b: 31 c0 xor eax,eax +40055d: b8 00 00 00 00 mov eax,0x0 +400562: 48 8b 55 f8 mov rdx,QWORD PTR [rbp-0x8] +400576: c9 leave +400577: c3 ret diff --git a/listings/chap14/rz/rz.c b/listings/chap14/rz/rz.c new file mode 100755 index 0000000..3d39939 --- /dev/null +++ b/listings/chap14/rz/rz.c @@ -0,0 +1,10 @@ +typedef unsigned long size_t; +__attribute__((noinline)) + int no_stack_frame( void ) { + char buffer[100]; + return 0; + } + +int main( int argc, char** argv ) { + return no_stack_frame(); +} diff --git a/listings/chap14/setjmp_volatile/setjmp_volatile.c b/listings/chap14/setjmp_volatile/setjmp_volatile.c new file mode 100755 index 0000000..35587f1 --- /dev/null +++ b/listings/chap14/setjmp_volatile/setjmp_volatile.c @@ -0,0 +1,18 @@ +#include +#include + +jmp_buf buf; + +int main( int argc, char** argv ) { + int var = 0; + volatile int b = 0; + setjmp( buf ); + if (b < 3) { + b++; + var ++; + printf( "\n\n%d\n", var ); + longjmp( buf, 1 ); + } + + return 0; +} diff --git a/listings/chap14/strict-aliasing/strict-aliasing.c b/listings/chap14/strict-aliasing/strict-aliasing.c new file mode 100755 index 0000000..e9d0f00 --- /dev/null +++ b/listings/chap14/strict-aliasing/strict-aliasing.c @@ -0,0 +1,37 @@ +#include +#include +#include +/* +void swap(int64_t* arg ) { + int32_t t; + + int32_t* v = (int32_t*)arg; + t = v[0]; + v[0] = v[1]; + v[1] = t; +} + +int main(void) { + int64_t x = 1; + swap( &x ); + printf( "%"PRId64"\n", x); + return 0; +}*/ +typedef uint64_t DWORD; +typedef uint32_t WORD; + +int SwapWords ( DWORD val ) +{ + WORD * p = (WORD*) &val; + WORD t; + t = p[0]; + p[0] = p[1]; + p[1] = t; + return val; +} + +int main() +{ + printf ( "%d\n", SwapWords(1) ); + return 0; +} diff --git a/listings/chap14/vararg/vararg.c b/listings/chap14/vararg/vararg.c new file mode 100755 index 0000000..9e47659 --- /dev/null +++ b/listings/chap14/vararg/vararg.c @@ -0,0 +1,18 @@ +#include +#include + +void printer( unsigned long argcount, ... ) { + va_list args; + unsigned long i; + va_start( args, argcount ); + for (i = 0; i < argcount; i++ ) + printf(" %d\n", va_arg(args, int ) ); + + va_end( args ); +} + + +int main () { + printer(10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 ); + return 0; +} diff --git a/listings/chap14/volatile_ex/volatile_ex.asm b/listings/chap14/volatile_ex/volatile_ex.asm new file mode 100755 index 0000000..fe9c8fc --- /dev/null +++ b/listings/chap14/volatile_ex/volatile_ex.asm @@ -0,0 +1,29 @@ +; these are two arguments for `printf` +mov esi,0x1 +mov edi,0x4005d4 + +; vol = 4 +mov DWORD PTR [rsp+0xc],0x4 + +; vol ++ +mov eax,DWORD PTR [rsp+0xc] +add eax,0x1 +mov DWORD PTR [rsp+0xc],eax + +xor eax,eax + +; printf( "%d\n", ordinary ) +; the `ordinary` is not even created in stack frame +; its final precomputed value 1 was placed in `rsi` in the first line! +call 4003e0 + +; the second argument is taken from memory, it is volatile! +mov esi,DWORD PTR [rsp+0xc] + +; First argument is the address of "%d\n" +mov edi,0x4005d4 +xor eax,eax + +; printf( "%d\n", vol ) +call 4003e0 +xor eax,eax diff --git a/listings/chap14/volatile_ex/volatile_ex.c b/listings/chap14/volatile_ex/volatile_ex.c new file mode 100755 index 0000000..3d78363 --- /dev/null +++ b/listings/chap14/volatile_ex/volatile_ex.c @@ -0,0 +1,11 @@ +#include + +int main( int argc, char** argv ) { + int ordinary = 0; + volatile int vol = 4; + ordinary++; + vol++; + printf( "%d\n", ordinary ); + printf( "%d\n", vol ); + return 0; +} diff --git a/listings/chap14/volatile_setjmp_o0/volatile_setjmp_o0.asm b/listings/chap14/volatile_setjmp_o0/volatile_setjmp_o0.asm new file mode 100755 index 0000000..392bd4d --- /dev/null +++ b/listings/chap14/volatile_setjmp_o0/volatile_setjmp_o0.asm @@ -0,0 +1,51 @@ +main: +push rbp +mov rbp,rsp +sub rsp,0x20 + +; `argc` and `argv` are saved in stack to make `rdi` and `rsi` available +mov DWORD PTR [rbp-0x14],edi +mov QWORD PTR [rbp-0x20],rsi + +; var = 0 +mov DWORD PTR [rbp-0x4],0x0 + +; b = 0 +mov DWORD PTR [rbp-0x8],0x0 + +; 0x600a40 is the address of `buf` (a global variable of type `jmp_buf`) +mov edi,0x600a40 +call 400470 <_setjmp@plt> + +; if (b < 3), the good branch is executed +; This is encoded by skipping several instructions to the `.endlabel` if b > 2 +mov eax,DWORD PTR [rbp-0x8] +cmp eax,0x2 +jg .endlabel + +; A fair increment +; b++ +mov eax,DWORD PTR [rbp-0x8] +add eax,0x1 +mov DWORD PTR [rbp-0x8],eax + +; var++ +add DWORD PTR [rbp-0x4],0x1 + +; `printf` call +mov eax,DWORD PTR [rbp-0x4] +mov esi,eax +mov edi,0x400684 +; There are no floating point arguments, thus rax = 0 +mov eax,0x0 +call 400450 + +; calling `longjmp` +mov esi,0x1 +mov edi,0x600a40 +call 400490 + +.endlabel: +mov eax,0x0 +leave +ret diff --git a/listings/chap14/volatile_setjmp_o2/volatile_setjmp_o2.asm b/listings/chap14/volatile_setjmp_o2/volatile_setjmp_o2.asm new file mode 100755 index 0000000..345ae28 --- /dev/null +++ b/listings/chap14/volatile_setjmp_o2/volatile_setjmp_o2.asm @@ -0,0 +1,48 @@ +main: + +; allocating memory in stack +sub rsp,0x18 + +; a `setjmp` argument, the address of `buf` +mov edi,0x600a40 + +; b = 0 +mov DWORD PTR [rsp+0xc],0x0 +; instructions are placed in the order different +; from C statements to make better use of pipeline and other inner +; CPU mechanisms. +call 400470 <_setjmp@plt> + +; `b` is read and checked in a fair way +mov eax,DWORD PTR [rsp+0xc] +cmp eax,0x2 +jle .branch + +; return 0 +xor eax,eax +add rsp,0x18 +ret + +.branch: + +mov eax,DWORD PTR [rsp+0xc] + +; the second argument of `printf` is var + 1 +; It was not even read from memory nor allocated. +; The computations were performed in compile time +mov esi,0x1 + +; The first argument of `printf` +mov edi,0x400674 + +; b = b + 1 +add eax,0x1 +mov DWORD PTR [rsp+0xc],eax + +xor eax,eax +call 400450 + +; longjmp( buf, 1 ) +mov esi,0x1 +mov edi,0x600a40 +call 400490 diff --git a/listings/chap14/vsprintf/vsprintf.c b/listings/chap14/vsprintf/vsprintf.c new file mode 100755 index 0000000..b03ab99 --- /dev/null +++ b/listings/chap14/vsprintf/vsprintf.c @@ -0,0 +1,16 @@ +#include +#include + +void logmsg( int client_id, const char* const str, ... ) { + va_list args; + char buffer[1024]; + char* bufptr = buffer; + + va_start( args, str ); + + bufptr += sprintf(bufptr, "from client %d :", client_id ); + vsprintf( bufptr, str, args ); + fprintf( stderr, "%s", buffer ); + + va_end( args ); +} diff --git a/listings/chap15/.asm b/listings/chap15/.asm new file mode 100755 index 0000000..1054c54 --- /dev/null +++ b/listings/chap15/.asm @@ -0,0 +1,12 @@ +global _start + +extern sofun + +section .text +_start: +call sofun + +; `exit` systel call +mov rdi, 0 +mov rax, 60 +syscall diff --git a/listings/chap15/cm-example/cm-example.c b/listings/chap15/cm-example/cm-example.c new file mode 100755 index 0000000..86e3f85 --- /dev/null +++ b/listings/chap15/cm-example/cm-example.c @@ -0,0 +1,17 @@ +char glob_small[100] = {1}; +char glob_big[10000000] = {1}; +static char loc_small[100] = {1}; +static char loc_big[10000000] = {1}; + +int global_f(void) { return 42; } +static int local_f(void) { return 42; } + +int main(void) { + glob_small[0] = 42; + glob_big[0] = 42; + loc_small[0] = 42; + loc_big[0] = 42; + global_f(); + local_f(); + return 0; +} diff --git a/listings/chap15/da_crt1/da_crt1 b/listings/chap15/da_crt1/da_crt1 new file mode 100755 index 0000000..724a55e --- /dev/null +++ b/listings/chap15/da_crt1/da_crt1 @@ -0,0 +1,18 @@ +/usr/lib/x86_64-linux-gnu/crt1.o: file format elf64-x86-64 + +Disassembly of section .text: + +0000000000000000 <_start>: +0: xor ebp,ebp +2: mov r9,rdx +5: pop rsi +6: mov rdx,rsp +9: and rsp,0xfffffffffffffff0 +d: push rax +e: push rsp +f: mov r8,0x0 +16: mov rcx,0x0 +1d: mov rdi,0x0 +24: call 29 <_start+0x29> +29: hlt + diff --git a/listings/chap15/da_crti/da_crti b/listings/chap15/da_crti/da_crti new file mode 100755 index 0000000..3425d56 --- /dev/null +++ b/listings/chap15/da_crti/da_crti @@ -0,0 +1,16 @@ +/usr/lib/x86_64-linux-gnu/crti.o: file format elf64-x86-64 + + +Disassembly of section .init: + +0000000000000000 <_init>: +0: sub rsp, 0x8 +4: mov rax, QWORD PTR [rip+0x0] # b <_init+0xb> +b: test rax, rax +e: je 15 <_init+0x15> +10: call 15 <_init+0x15> + +Disassembly of section .fini: + +0000000000000000 <_fini>: +0: sub rsp, 0x8 diff --git a/listings/chap15/da_crtn/da_crtn b/listings/chap15/da_crtn/da_crtn new file mode 100755 index 0000000..b8ecdee --- /dev/null +++ b/listings/chap15/da_crtn/da_crtn @@ -0,0 +1,14 @@ +/usr/lib/x86_64-linux-gnu/crtn.o: file format elf64-x86-64 + +Disassembly of section .init: + +0000000000000000 <.init>: +0: add rsp,0x8 +4: ret + +Disassembly of section .fini: + +0000000000000000 <.fini>: +0: add rsp,0x8 +4: ret + diff --git a/listings/chap15/dasm_init_fini/dasm_init_fini b/listings/chap15/dasm_init_fini/dasm_init_fini new file mode 100755 index 0000000..c390f52 --- /dev/null +++ b/listings/chap15/dasm_init_fini/dasm_init_fini @@ -0,0 +1,34 @@ +Disassembly of section .init: + +00000000004005d8 <_init>: +4005d8: sub rsp,0x8 +4005dc: mov rax,QWORD PTR [rip+0x200a15] # 600ff8 <_DYNAMIC+0x1e0> +4005e3: test rax,rax +4005e6: je 4005ed <_init+0x15> +4005e8: call 400650 <__libc_start_main@plt+0x10> +4005ed: add rsp,0x8 +4005f1: ret + +Disassembly of section .text: + +0000000000400660 <_start>: +400660: xor ebp,ebp +400662: mov r9,rdx +400665: pop rsi +400666: mov rdx,rsp +400669: and rsp,0xfffffffffffffff0 +40066d: push rax +40066e: push rsp +40066f: mov r8,0x400800 +400676: mov rcx,0x400790 +40067d: mov rdi,0x400756 +400684: call 400640 <__libc_start_main@plt> +400689: hlt + +Disassembly of section .fini: + +0000000000400804 <_fini>: +400804: sub rsp,0x8 +400808: add rsp,0x8 +40080c: ret + diff --git a/listings/chap15/dynlib/dynlib.c b/listings/chap15/dynlib/dynlib.c new file mode 100755 index 0000000..24ac42c --- /dev/null +++ b/listings/chap15/dynlib/dynlib.c @@ -0,0 +1,7 @@ +#include + +extern int global; +void libfun(int value) { + printf( "param: %d\n", value ); + printf( "global: %d\n", global ); +} diff --git a/listings/chap15/ex1-lib/ex1-lib.asm b/listings/chap15/ex1-lib/ex1-lib.asm new file mode 100755 index 0000000..b5b53f6 --- /dev/null +++ b/listings/chap15/ex1-lib/ex1-lib.asm @@ -0,0 +1,16 @@ +extern _GLOBAL_OFFSET_TABLE_ +global sofun:function + +section .rodata +msg: db "SO function called", 10 +.end: + +section .text +sofun: +mov rax, 1 +mov rdi, 1 +lea rsi, [rel msg] +mov rdx, msg.end - msg +syscall +ret + diff --git a/listings/chap15/ex1-main/ex1-main.asm b/listings/chap15/ex1-main/ex1-main.asm new file mode 100755 index 0000000..8d55671 --- /dev/null +++ b/listings/chap15/ex1-main/ex1-main.asm @@ -0,0 +1,13 @@ +extern _GLOBAL_OFFSET_TABLE_ +global _start + +extern sofun + +section .text +_start: +call sofun wrt ..plt + +; `exit` system call +mov rdi, 0 +mov rax, 60 +syscall diff --git a/listings/chap15/ex1-makefile/ex1-makefile b/listings/chap15/ex1-makefile/ex1-makefile new file mode 100755 index 0000000..096b7c6 --- /dev/null +++ b/listings/chap15/ex1-makefile/ex1-makefile @@ -0,0 +1,13 @@ + +main: main.o lib.so + ld --dynamic-linker=/lib64/ld-linux-x86-64.so.2 main.o lib.so -o main + +lib.so: lib.o + ld -shared lib.o -o lib.so + +lib.o: + nasm -felf64 lib.asm -o lib.o + +main.o: main.asm + nasm -felf64 main.asm -o main.o + diff --git a/listings/chap15/ex2-lib/ex2-lib.asm b/listings/chap15/ex2-lib/ex2-lib.asm new file mode 100755 index 0000000..9b6fb4b --- /dev/null +++ b/listings/chap15/ex2-lib/ex2-lib.asm @@ -0,0 +1,14 @@ +extern _GLOBAL_OFFSET_TABLE_ +global sofun:func + +extern msg + +section .text +sofun: +mov rax, 1 +mov rdi, 1 +mov rsi, [rel msg wrt ..got] +mov rdx, 50 +syscall +ret + diff --git a/listings/chap15/ex2-main/ex2-main.asm b/listings/chap15/ex2-main/ex2-main.asm new file mode 100755 index 0000000..23f1e1d --- /dev/null +++ b/listings/chap15/ex2-main/ex2-main.asm @@ -0,0 +1,19 @@ +extern _GLOBAL_OFFSET_TABLE_ +global _start + +extern sofun + +global msg:data (msg.end - msg) + +section .rodata +msg: db "SO function called -- message is stored in 'main'", 10 +.end: + +section .text +_start: +call sofun wrt ..plt + +mov rdi, 0 +mov rax, 60 +syscall + diff --git a/listings/chap15/ex3-lib/ex3-lib.asm b/listings/chap15/ex3-lib/ex3-lib.asm new file mode 100755 index 0000000..6b6796e --- /dev/null +++ b/listings/chap15/ex3-lib/ex3-lib.asm @@ -0,0 +1,28 @@ +extern _GLOBAL_OFFSET_TABLE_ + +extern commonmsg +extern mainfun + +global fun1:function + +section .rodata +msg: db "fun1", 10 + +section .text +fun1: + mov rax, 1 + mov rdi, 1 + lea rsi, [rel msg] + mov rdx, 6 + syscall + call fun2 + call mainfun wrt ..plt + ret + +fun2: + mov rax, 1 + mov rdi, 1 + mov rsi, [rel commonmsg wrt ..got] + mov rdx, 5 + syscall + ret diff --git a/listings/chap15/ex3-main/ex3-main.asm b/listings/chap15/ex3-main/ex3-main.asm new file mode 100755 index 0000000..ca60736 --- /dev/null +++ b/listings/chap15/ex3-main/ex3-main.asm @@ -0,0 +1,29 @@ +extern _GLOBAL_OFFSET_TABLE_ + +extern fun1 + +global commonmsg:data commonmsg.end - commonmsg +global mainfun:function +global _start + +section .rodata +commonmsg: db "fun2", 10, 0 +.end: + +mainfunmsg: db "mainfun", 10, 0 + + +section .text +_start: + call fun1 wrt ..plt + mov rax, 60 + mov rdi, 0 + syscall + +mainfun: + mov rax, 1 + mov rdi, 1 + mov rsi, mainfunmsg + mov rdx, 8 + syscall + ret diff --git a/listings/chap15/ex4-Makefile/ex4-Makefile b/listings/chap15/ex4-Makefile/ex4-Makefile new file mode 100755 index 0000000..6bb2548 --- /dev/null +++ b/listings/chap15/ex4-Makefile/ex4-Makefile @@ -0,0 +1,18 @@ + +all: main + +main: main.o lib.so + gcc -o main main.o lib.so + +lib.so: lib.o + gcc -shared lib.o -o lib.so + +lib.o: lib.asm + nasm -felf64 lib.asm -o lib.o + +main.o: main.asm + gcc -ansi -c main.c -o main.o + +clean: + rm -rf *.o *.so main + diff --git a/listings/chap15/ex4-lib/ex4-lib.asm b/listings/chap15/ex4-lib/ex4-lib.asm new file mode 100755 index 0000000..fee85cf --- /dev/null +++ b/listings/chap15/ex4-lib/ex4-lib.asm @@ -0,0 +1,20 @@ +extern _GLOBAL_OFFSET_TABLE_ + +extern puts + +global sostr:data (sostr.end - sostr) +global sofun:function + +section .rodata +sostr: db "sostring", 10, 0 +.end: + +localstr: db "localstr", 10, 0 + +section .text +sofun: + lea rdi, [rel localstr] + call puts wrt ..plt + mov rax, 42 + ret + diff --git a/listings/chap15/ex4-main/ex4-main.c b/listings/chap15/ex4-main/ex4-main.c new file mode 100755 index 0000000..31598a9 --- /dev/null +++ b/listings/chap15/ex4-main/ex4-main.c @@ -0,0 +1,11 @@ +#include + +extern int sofun( void ); +extern const char sostr[]; + +int main( void ) { + printf( "%d\n", sofun() ); + puts( sostr ); + return 0; +} + diff --git a/listings/chap15/gcc_alias/da b/listings/chap15/gcc_alias/da new file mode 100755 index 0000000..33edea7 --- /dev/null +++ b/listings/chap15/gcc_alias/da @@ -0,0 +1,160 @@ + +a.out: file format elf64-x86-64 + + +Disassembly of section .init: + +00000000000005f8 <_init>: + 5f8: 48 83 ec 08 sub rsp,0x8 + 5fc: 48 8b 05 dd 09 20 00 mov rax,QWORD PTR [rip+0x2009dd] # 200fe0 <_DYNAMIC+0x1d0> + 603: 48 85 c0 test rax,rax + 606: 74 05 je 60d <_init+0x15> + 608: e8 53 00 00 00 call 660 + 60d: 48 83 c4 08 add rsp,0x8 + 611: c3 ret + +Disassembly of section .plt: + +0000000000000620 : + 620: ff 35 e2 09 20 00 push QWORD PTR [rip+0x2009e2] # 201008 <_GLOBAL_OFFSET_TABLE_+0x8> + 626: ff 25 e4 09 20 00 jmp QWORD PTR [rip+0x2009e4] # 201010 <_GLOBAL_OFFSET_TABLE_+0x10> + 62c: 0f 1f 40 00 nop DWORD PTR [rax+0x0] + +0000000000000630 : + 630: ff 25 e2 09 20 00 jmp QWORD PTR [rip+0x2009e2] # 201018 <_GLOBAL_OFFSET_TABLE_+0x18> + 636: 68 00 00 00 00 push 0x0 + 63b: e9 e0 ff ff ff jmp 620 <_init+0x28> + +0000000000000640 : + 640: ff 25 da 09 20 00 jmp QWORD PTR [rip+0x2009da] # 201020 <_GLOBAL_OFFSET_TABLE_+0x20> + 646: 68 01 00 00 00 push 0x1 + 64b: e9 d0 ff ff ff jmp 620 <_init+0x28> + +0000000000000650 : + 650: ff 25 d2 09 20 00 jmp QWORD PTR [rip+0x2009d2] # 201028 <_GLOBAL_OFFSET_TABLE_+0x28> + 656: 68 02 00 00 00 push 0x2 + 65b: e9 c0 ff ff ff jmp 620 <_init+0x28> + +Disassembly of section .plt.got: + +0000000000000660 <.plt.got>: + 660: ff 25 7a 09 20 00 jmp QWORD PTR [rip+0x20097a] # 200fe0 <_DYNAMIC+0x1d0> + 666: 66 90 xchg ax,ax + 668: ff 25 8a 09 20 00 jmp QWORD PTR [rip+0x20098a] # 200ff8 <_DYNAMIC+0x1e8> + 66e: 66 90 xchg ax,ax + +Disassembly of section .text: + +0000000000000670 : + 670: 48 8d 3d c9 09 20 00 lea rdi,[rip+0x2009c9] # 201040 <__TMC_END__> + 677: 48 8d 05 c9 09 20 00 lea rax,[rip+0x2009c9] # 201047 <__TMC_END__+0x7> + 67e: 55 push rbp + 67f: 48 29 f8 sub rax,rdi + 682: 48 89 e5 mov rbp,rsp + 685: 48 83 f8 0e cmp rax,0xe + 689: 76 15 jbe 6a0 + 68b: 48 8b 05 3e 09 20 00 mov rax,QWORD PTR [rip+0x20093e] # 200fd0 <_DYNAMIC+0x1c0> + 692: 48 85 c0 test rax,rax + 695: 74 09 je 6a0 + 697: 5d pop rbp + 698: ff e0 jmp rax + 69a: 66 0f 1f 44 00 00 nop WORD PTR [rax+rax*1+0x0] + 6a0: 5d pop rbp + 6a1: c3 ret + 6a2: 0f 1f 40 00 nop DWORD PTR [rax+0x0] + 6a6: 66 2e 0f 1f 84 00 00 nop WORD PTR cs:[rax+rax*1+0x0] + 6ad: 00 00 00 + +00000000000006b0 : + 6b0: 48 8d 3d 89 09 20 00 lea rdi,[rip+0x200989] # 201040 <__TMC_END__> + 6b7: 48 8d 35 82 09 20 00 lea rsi,[rip+0x200982] # 201040 <__TMC_END__> + 6be: 55 push rbp + 6bf: 48 29 fe sub rsi,rdi + 6c2: 48 89 e5 mov rbp,rsp + 6c5: 48 c1 fe 03 sar rsi,0x3 + 6c9: 48 89 f0 mov rax,rsi + 6cc: 48 c1 e8 3f shr rax,0x3f + 6d0: 48 01 c6 add rsi,rax + 6d3: 48 d1 fe sar rsi,1 + 6d6: 74 18 je 6f0 + 6d8: 48 8b 05 11 09 20 00 mov rax,QWORD PTR [rip+0x200911] # 200ff0 <_DYNAMIC+0x1e0> + 6df: 48 85 c0 test rax,rax + 6e2: 74 0c je 6f0 + 6e4: 5d pop rbp + 6e5: ff e0 jmp rax + 6e7: 66 0f 1f 84 00 00 00 nop WORD PTR [rax+rax*1+0x0] + 6ee: 00 00 + 6f0: 5d pop rbp + 6f1: c3 ret + 6f2: 0f 1f 40 00 nop DWORD PTR [rax+0x0] + 6f6: 66 2e 0f 1f 84 00 00 nop WORD PTR cs:[rax+rax*1+0x0] + 6fd: 00 00 00 + +0000000000000700 <__do_global_dtors_aux>: + 700: 80 3d 35 09 20 00 00 cmp BYTE PTR [rip+0x200935],0x0 # 20103c <_edata> + 707: 75 27 jne 730 <__do_global_dtors_aux+0x30> + 709: 48 83 3d e7 08 20 00 cmp QWORD PTR [rip+0x2008e7],0x0 # 200ff8 <_DYNAMIC+0x1e8> + 710: 00 + 711: 55 push rbp + 712: 48 89 e5 mov rbp,rsp + 715: 74 0c je 723 <__do_global_dtors_aux+0x23> + 717: 48 8b 3d 12 09 20 00 mov rdi,QWORD PTR [rip+0x200912] # 201030 <__dso_handle> + 71e: e8 45 ff ff ff call 668 + 723: e8 48 ff ff ff call 670 + 728: 5d pop rbp + 729: c6 05 0c 09 20 00 01 mov BYTE PTR [rip+0x20090c],0x1 # 20103c <_edata> + 730: f3 c3 repz ret + 732: 0f 1f 40 00 nop DWORD PTR [rax+0x0] + 736: 66 2e 0f 1f 84 00 00 nop WORD PTR cs:[rax+rax*1+0x0] + 73d: 00 00 00 + +0000000000000740 : + 740: 48 8d 3d c1 06 20 00 lea rdi,[rip+0x2006c1] # 200e08 <__JCR_END__> + 747: 48 83 3f 00 cmp QWORD PTR [rdi],0x0 + 74b: 75 0b jne 758 + 74d: e9 5e ff ff ff jmp 6b0 + 752: 66 0f 1f 44 00 00 nop WORD PTR [rax+rax*1+0x0] + 758: 48 8b 05 89 08 20 00 mov rax,QWORD PTR [rip+0x200889] # 200fe8 <_DYNAMIC+0x1d8> + 75f: 48 85 c0 test rax,rax + 762: 74 e9 je 74d + 764: 55 push rbp + 765: 48 89 e5 mov rbp,rsp + 768: ff d0 call rax + 76a: 5d pop rbp + 76b: e9 40 ff ff ff jmp 6b0 + +0000000000000770 : + 770: 55 push rbp + 771: 48 89 e5 mov rbp,rsp + 774: 48 8d 3d 5e 00 00 00 lea rdi,[rip+0x5e] # 7d9 <_fini+0x9> + 77b: e8 b0 fe ff ff call 630 + 780: 90 nop + 781: 5d pop rbp + 782: c3 ret + +0000000000000783 : + 783: 55 push rbp + 784: 48 89 e5 mov rbp,rsp + 787: 48 8b 05 4a 08 20 00 mov rax,QWORD PTR [rip+0x20084a] # 200fd8 <_DYNAMIC+0x1c8> + 78e: 8b 00 mov eax,DWORD PTR [rax] + 790: 89 c6 mov esi,eax + 792: 48 8d 3d 46 00 00 00 lea rdi,[rip+0x46] # 7df <_fini+0xf> + 799: b8 00 00 00 00 mov eax,0x0 + 79e: e8 ad fe ff ff call 650 + 7a3: 8b 05 8f 08 20 00 mov eax,DWORD PTR [rip+0x20088f] # 201038 + 7a9: 89 c6 mov esi,eax + 7ab: 48 8d 3d 2d 00 00 00 lea rdi,[rip+0x2d] # 7df <_fini+0xf> + 7b2: b8 00 00 00 00 mov eax,0x0 + 7b7: e8 94 fe ff ff call 650 + 7bc: e8 7f fe ff ff call 640 + 7c1: e8 aa ff ff ff call 770 + 7c6: b8 00 00 00 00 mov eax,0x0 + 7cb: 5d pop rbp + 7cc: c3 ret + +Disassembly of section .fini: + +00000000000007d0 <_fini>: + 7d0: 48 83 ec 08 sub rsp,0x8 + 7d4: 48 83 c4 08 add rsp,0x8 + 7d8: c3 ret diff --git a/listings/chap15/gcc_alias/gcc_alias.c b/listings/chap15/gcc_alias/gcc_alias.c new file mode 100755 index 0000000..a379024 --- /dev/null +++ b/listings/chap15/gcc_alias/gcc_alias.c @@ -0,0 +1,23 @@ +#include + +int global = 42; + +extern int global_alias +__attribute__((alias ("global"), visibility ("hidden" ) )); + + +void fun( void ) { + puts("1337\n"); +} + +extern void fun_alias( void ) +__attribute__((alias ("fun"), visibility ("hidden" ) )); + +int tester(void) { + printf( "%d\n", global ); + printf( "%d\n", global_alias ); + + fun(); + fun_alias(); + return 0; +} diff --git a/listings/chap15/gcc_aliased_gain/gcc_aliased_gain.asm b/listings/chap15/gcc_aliased_gain/gcc_aliased_gain.asm new file mode 100755 index 0000000..03099ae --- /dev/null +++ b/listings/chap15/gcc_aliased_gain/gcc_aliased_gain.asm @@ -0,0 +1,22 @@ +; global -> rsi +787: mov rax,QWORD PTR [rip+0x20084a] # 200fd8 <_DYNAMIC+0x1c8> +78e: mov eax,DWORD PTR [rax] +790: mov esi,eax + +792: lea rdi,[rip+0x46] # 7df <_fini+0xf> +799: mov eax,0x0 +79e: call 650 + +; global_alias -> rsi +7a3: mov eax,DWORD PTR [rip+0x20088f] # 201038 +7a9: mov esi,eax + +7ab: lea rdi,[rip+0x2d] # 7df <_fini+0xf> +7b2: mov eax,0x0 +7b7: call 650 + +; calling global `fun` +7bc: call 640 + +; calling aliased `fun` directly +7c1: call 770 diff --git a/listings/chap15/got_plt_dump_ex/got_plt_dump_ex.c b/listings/chap15/got_plt_dump_ex/got_plt_dump_ex.c new file mode 100755 index 0000000..720c132 --- /dev/null +++ b/listings/chap15/got_plt_dump_ex/got_plt_dump_ex.c @@ -0,0 +1,4 @@ +Contents of section .got.plt: +0x601000 180e6000 00000000 00000000 00000000 +0x601010 00000000 00000000 86054000 00000000 +0x601020 96054000 00000000 diff --git a/listings/chap15/ld_preload_effect/ld_preload_effect b/listings/chap15/ld_preload_effect/ld_preload_effect new file mode 100755 index 0000000..6caa4d8 --- /dev/null +++ b/listings/chap15/ld_preload_effect/ld_preload_effect @@ -0,0 +1,6 @@ +> export LD_PRELOAD= +> ./a.out +Hello, world! +> export LD_PRELOAD=$PWD/prelib.so +> ./a.out +We took control over your C library! diff --git a/listings/chap15/libfun/libfun b/listings/chap15/libfun/libfun new file mode 100755 index 0000000..78354e6 --- /dev/null +++ b/listings/chap15/libfun/libfun @@ -0,0 +1,35 @@ +00000000000006d0 : + +# Function prologue + 6d0: 55 push rbp + 6d1: 48 89 e5 mov rbp,rsp + 6d4: 48 83 ec 10 sub rsp,0x10 + +# Second argument for printf( "param: %d\n", value ); + 6d8: 89 7d fc mov DWORD PTR [rbp-0x4],edi + 6db: 8b 45 fc mov eax,DWORD PTR [rbp-0x4] + 6de: 89 c6 mov esi,eax + +# First argument for printf( "param: %d\n", value ); + 6e0: 48 8d 3d 32 00 00 00 lea rdi,[rip+0x32] + +# Printf call; zero XMM registers used + 6e7: b8 00 00 00 00 mov eax,0x0 + 6ec: e8 bf fe ff ff call 5b0 + +# Second argument for printf( "global: %d\n", global ); + 6f1: 48 8b 05 e0 08 20 00 mov rax,QWORD PTR [rip+0x2008e0] + 6f8: 8b 00 mov eax,DWORD PTR [rax] + 6fa: 89 c6 mov esi,eax + +# First argument for printf( "global: %d\n", global ); + 6fc: 48 8d 3d 21 00 00 00 lea rdi,[rip+0x21] + +# Printf call; zero XMM registers used + 703: b8 00 00 00 00 mov eax,0x0 + 708: e8 a3 fe ff ff call 5b0 + +# Function epilogue + 70d: 90 nop + 70e: c9 leave + 70f: c3 ret diff --git a/listings/chap15/mainlib/mainlib.c b/listings/chap15/mainlib/mainlib.c new file mode 100755 index 0000000..112e000 --- /dev/null +++ b/listings/chap15/mainlib/mainlib.c @@ -0,0 +1,8 @@ +extern void libfun( int value ); + +int global = 100; + +int main( void ) { + libfun( 42 ); + return 0; +} diff --git a/listings/chap15/mc-small/mc-small b/listings/chap15/mc-small/mc-small new file mode 100755 index 0000000..c55b4d2 --- /dev/null +++ b/listings/chap15/mc-small/mc-small @@ -0,0 +1,11 @@ +; glob_small[0] = 42; +4004f0: c6 05 49 0b 20 00 2a mov BYTE PTR [rip+0x200b49],0x2a + +; loc_small[0] = 42; +4004fe: c6 05 3b a2 b8 00 2a mov BYTE PTR [rip+0xb8a23b],0x2a + +; global_f(); +40050c: e8 c5 ff ff ff call 4004d6 + +; local_f(); +400511: e8 cb ff ff ff call 4004e1 diff --git a/listings/chap15/plt_rw/plt_rw.asm b/listings/chap15/plt_rw/plt_rw.asm new file mode 100755 index 0000000..0146b57 --- /dev/null +++ b/listings/chap15/plt_rw/plt_rw.asm @@ -0,0 +1,35 @@ +Disassembly of section .init: + +0000000000400550 <_init>: +sub rsp,0x8 +mov rax,QWORD PTR [rip+0x200a9d] # 600ff8 <_DYNAMIC+0x1e0> +test rax,rax +je 400565 <_init+0x15> +call 4005a0 <__libc_start_main@plt+0x10> +add rsp,0x8 +ret +Disassembly of section .plt: + +0000000000400570 : +push QWORD PTR [rip+0x200a92] # 601008 <_GLOBAL_OFFSET_TABLE_+0x8> +jmp QWORD PTR [rip+0x200a94] # 601010 <_GLOBAL_OFFSET_TABLE_+0x10> +nop DWORD PTR [rax+0x0] + +0000000000400580 : +jmp QWORD PTR [rip+0x200a92] # 601018 <_GLOBAL_OFFSET_TABLE_+0x18> +push 0x0 +jmp 400570 <_init+0x20> + +0000000000400590 <__libc_start_main@plt>: +jmp QWORD PTR [rip+0x200a8a] # 601020 <_GLOBAL_OFFSET_TABLE_+0x20> +push 0x1 +jmp 400570 <_init+0x20> + + +Disassembly of section .got: +0000000000600ff8 <.got>: +... +Disassembly of section .got.plt: + +0000000000601000 <_GLOBAL_OFFSET_TABLE_>: +... diff --git a/listings/chap15/plt_sketch/plt_sketch.asm b/listings/chap15/plt_sketch/plt_sketch.asm new file mode 100755 index 0000000..de1b9ea --- /dev/null +++ b/listings/chap15/plt_sketch/plt_sketch.asm @@ -0,0 +1,21 @@ +; somewhere in the program +call func@plt + + +; PLT +PLT_0: ; the common part +call resolver + +... + +PLT_n: func@plt: +jmp [GOT_n] +PLT_n_first: +; here the arguments for resolver are prepared +jmp PLT_0 + + +GOT: +... +GOT_n: +dq PLT_n_first diff --git a/listings/chap15/prelib/prelib.c b/listings/chap15/prelib/prelib.c new file mode 100755 index 0000000..3f70241 --- /dev/null +++ b/listings/chap15/prelib/prelib.c @@ -0,0 +1,4 @@ +#include +int puts( const char* str ) { + return printf("We took control over your C library! \n"); +} diff --git a/listings/chap15/preload_launcher/preload_launcher.c b/listings/chap15/preload_launcher/preload_launcher.c new file mode 100755 index 0000000..2415757 --- /dev/null +++ b/listings/chap15/preload_launcher/preload_launcher.c @@ -0,0 +1,6 @@ +#include + +int main(void) { + puts("Hello, world!"); + return 0; +} diff --git a/listings/chap15/so_adapter/so_adapter.c b/listings/chap15/so_adapter/so_adapter.c new file mode 100755 index 0000000..3ba7121 --- /dev/null +++ b/listings/chap15/so_adapter/so_adapter.c @@ -0,0 +1,9 @@ + +static int _function( int x ) { return x + 1; } + +void otherfunction( ) { + printf(" %d \n", _function( 41 ) ); +} + +int function( int x ) { return _function( x ); } + diff --git a/listings/chap15/visibility_symbol/visibility_symbol.c b/listings/chap15/visibility_symbol/visibility_symbol.c new file mode 100755 index 0000000..4be4d04 --- /dev/null +++ b/listings/chap15/visibility_symbol/visibility_symbol.c @@ -0,0 +1,3 @@ +int +__attribute__(( visibility( "default" ) )) +func(int x) { return 42; } diff --git a/listings/chap16/binsearch_prefetch_off/binsearch_prefetch_off b/listings/chap16/binsearch_prefetch_off/binsearch_prefetch_off new file mode 100755 index 0000000..1c1d8c7 --- /dev/null +++ b/listings/chap16/binsearch_prefetch_off/binsearch_prefetch_off @@ -0,0 +1,25 @@ +> gcc -O3 prefetch.c -o prefetch_off && /usr/bin/time -v ./prefetch_off + + Command being timed: "./prefetch_off" + User time (seconds): 7.56 + System time (seconds): 0.02 + Percent of CPU this job got: 100% + Elapsed (wall clock) time (h:mm:ss or m:ss): 0:07.58 + Average shared text size (kbytes): 0 + Average unshared data size (kbytes): 0 + Average stack size (kbytes): 0 + Average total size (kbytes): 0 + Maximum resident set size (kbytes): 66432 + Average resident set size (kbytes): 0 + Major (requiring I/O) page faults: 0 + Minor (reclaiming a frame) page faults: 16444 + Voluntary context switches: 1 + Involuntary context switches: 51 + Swaps: 0 + File system inputs: 0 + File system outputs: 0 + Socket messages sent: 0 + Socket messages received: 0 + Signals delivered: 0 + Page size (bytes): 4096 + Exit status: 0 diff --git a/listings/chap16/binsearch_prefetch_off_cachegrind/binsearch_prefetch_off_cachegrind b/listings/chap16/binsearch_prefetch_off_cachegrind/binsearch_prefetch_off_cachegrind new file mode 100755 index 0000000..3b41b28 --- /dev/null +++ b/listings/chap16/binsearch_prefetch_off_cachegrind/binsearch_prefetch_off_cachegrind @@ -0,0 +1,22 @@ +==25479== Cachegrind, a cache and branch-prediction profiler +==25479== Copyright (C) 2002-2015, and GNU GPL'd, by Nicholas Nethercote et al. +==25479== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info +==25479== Command: ./prefetch_off +==25479== +--25479-- warning: L3 cache found, using its data for the LL simulation. +==25479== +==25479== I refs: 2,529,064,580 +==25479== I1 misses: 778 +==25479== LLi misses: 774 +==25479== I1 miss rate: 0.00% +==25479== LLi miss rate: 0.00% +==25479== +==25479== D refs: 404,809,999 (335,588,367 rd + 69,221,632 wr) +==25479== D1 misses: 160,885,105 (159,835,971 rd + 1,049,134 wr) +==25479== LLd misses: 133,467,980 (132,418,879 rd + 1,049,101 wr) +==25479== D1 miss rate: 39.7% ( 47.6% + 1.5% ) +==25479== LLd miss rate: 33.0% ( 39.5% + 1.5% ) +==25479== +==25479== LL refs: 160,885,883 (159,836,749 rd + 1,049,134 wr) +==25479== LL misses: 133,468,754 (132,419,653 rd + 1,049,101 wr) +==25479== LL miss rate: 4.5% ( 4.6% + 1.5% ) diff --git a/listings/chap16/binsearch_prefetch_on/binsearch_prefetch_on b/listings/chap16/binsearch_prefetch_on/binsearch_prefetch_on new file mode 100755 index 0000000..d1d6ec8 --- /dev/null +++ b/listings/chap16/binsearch_prefetch_on/binsearch_prefetch_on @@ -0,0 +1,25 @@ +> gcc -O3 prefetch.c -o prefetch_off && /usr/bin/time -v ./prefetch_off + + Command being timed: "./prefetch_on" + User time (seconds): 6.56 + System time (seconds): 0.01 + Percent of CPU this job got: 100% + Elapsed (wall clock) time (h:mm:ss or m:ss): 0:06.57 + Average shared text size (kbytes): 0 + Average unshared data size (kbytes): 0 + Average stack size (kbytes): 0 + Average total size (kbytes): 0 + Maximum resident set size (kbytes): 66512 + Average resident set size (kbytes): 0 + Major (requiring I/O) page faults: 0 + Minor (reclaiming a frame) page faults: 16443 + Voluntary context switches: 1 + Involuntary context switches: 42 + Swaps: 0 + File system inputs: 0 + File system outputs: 0 + Socket messages sent: 0 + Socket messages received: 0 + Signals delivered: 0 + Page size (bytes): 4096 + Exit status: 0 diff --git a/listings/chap16/binsearch_prefetch_on_cachegrind/binsearch_prefetch_on_cachegrind b/listings/chap16/binsearch_prefetch_on_cachegrind/binsearch_prefetch_on_cachegrind new file mode 100755 index 0000000..f0332d7 --- /dev/null +++ b/listings/chap16/binsearch_prefetch_on_cachegrind/binsearch_prefetch_on_cachegrind @@ -0,0 +1,22 @@ +==26238== Cachegrind, a cache and branch-prediction profiler +==26238== Copyright (C) 2002-2015, and GNU GPL'd, by Nicholas Nethercote et al. +==26238== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info +==26238== Command: ./prefetch_on +==26238== +--26238-- warning: L3 cache found, using its data for the LL simulation. +==26238== +==26238== I refs: 3,686,688,760 +==26238== I1 misses: 777 +==26238== LLi misses: 773 +==26238== I1 miss rate: 0.00% +==26238== LLi miss rate: 0.00% +==26238== +==26238== D refs: 404,810,009 (335,588,374 rd + 69,221,635 wr) +==26238== D1 misses: 160,887,823 (159,838,690 rd + 1,049,133 wr) +==26238== LLd misses: 133,488,742 (132,439,642 rd + 1,049,100 wr) +==26238== D1 miss rate: 39.7% ( 47.6% + 1.5% ) +==26238== LLd miss rate: 33.0% ( 39.5% + 1.5% ) +==26238== +==26238== LL refs: 160,888,600 (159,839,467 rd + 1,049,133 wr) +==26238== LL misses: 133,489,515 (132,440,415 rd + 1,049,100 wr) +==26238== LL miss rate: 3.3% ( 3.3% + 1.5% ) diff --git a/listings/chap16/cache_bypass_intrinsics/cache_bypass_intrinsics.c b/listings/chap16/cache_bypass_intrinsics/cache_bypass_intrinsics.c new file mode 100755 index 0000000..f87b258 --- /dev/null +++ b/listings/chap16/cache_bypass_intrinsics/cache_bypass_intrinsics.c @@ -0,0 +1,12 @@ +#include +void _mm_stream_si32(int *p, int a); +void _mm_stream_si128(int *p, __m128i a); +void _mm_stream_pd(double *p, __m128d a); + +#include +void _mm_stream_pi(__m64 *p, __m64 a); +void _mm_stream_ps(float *p, __m128 a); + +#include +void _mm_stream_sd(double *p, __m128d a); +void _mm_stream_ss(float *p, __m128 a); diff --git a/listings/chap16/cachegrind_matrix_bad/cachegrind_matrix_bad b/listings/chap16/cachegrind_matrix_bad/cachegrind_matrix_bad new file mode 100755 index 0000000..7ecd4d8 --- /dev/null +++ b/listings/chap16/cachegrind_matrix_bad/cachegrind_matrix_bad @@ -0,0 +1,21 @@ +> valgrind --tool=cachegrind ./matrix_init_ra + +==17022== Command: ./matrix_init_ra +==17022== +--17022-- warning: L3 cache found, using its data for the LL simulation. +==17022== +==17022== I refs: 268,623,230 +==17022== I1 misses: 809 +==17022== LLi misses: 804 +==17022== I1 miss rate: 0.00% +==17022== LLi miss rate: 0.00% +==17022== +==17022== D refs: 67,163,682 (40,974 rd + 67,122,708 wr) +==17022== D1 misses: 67,111,793 ( 2,384 rd + 67,109,409 wr) +==17022== LLd misses: 67,111,408 ( 2,034 rd + 67,109,374 wr) +==17022== D1 miss rate: 99.9% ( 5.8% + 100.0% ) +==17022== LLd miss rate: 99.9% ( 5.0% + 100.0% ) +==17022== +==17022== LL refs: 67,112,602 ( 3,193 rd + 67,109,409 wr) +==17022== LL misses: 67,112,212 ( 2,838 rd + 67,109,374 wr) +==17022== LL miss rate: 20.0% ( 0.0% + 100.0% ) diff --git a/listings/chap16/common_subexpression/common_subexpression.asm b/listings/chap16/common_subexpression/common_subexpression.asm new file mode 100755 index 0000000..c5b0a50 --- /dev/null +++ b/listings/chap16/common_subexpression/common_subexpression.asm @@ -0,0 +1,12 @@ +0000000000400516 : +; rsi = x + 2 +400516: 8d 77 02 lea esi,[rdi+0x2] +400519: 31 c0 xor eax,eax +40051b: 0f af f7 imul esi,edi +; rsi = x*(x+2) +40051e: bf b4 05 40 00 mov edi,0x4005b4 +; rdx = rsi-1 = x*(x+2) - 1 +400523: 8d 56 ff lea edx,[rsi-0x1] +; rsi = rsi + 1 = x*(x+2) - 1 +400526: ff c6 inc esi +400528: e9 b3 fe ff ff jmp 4003e0 diff --git a/listings/chap16/common_subexpression/common_subexpression.c b/listings/chap16/common_subexpression/common_subexpression.c new file mode 100755 index 0000000..491561f --- /dev/null +++ b/listings/chap16/common_subexpression/common_subexpression.c @@ -0,0 +1,13 @@ +#include + +__attribute__((noinline)) + void test(int x) { + printf("%d %d", + x*x + 2*x + 1, + x*x + 2*x - 1 ); + } + +int main(int argc, char** argv) { + test( argc ); + return 0; +} diff --git a/listings/chap16/constant_propagation/constant_propagation.asm b/listings/chap16/constant_propagation/constant_propagation.asm new file mode 100755 index 0000000..0efe9ce --- /dev/null +++ b/listings/chap16/constant_propagation/constant_propagation.asm @@ -0,0 +1,3 @@ +00000000004004c0 : +4004c0: 8d 47 2a lea eax,[rdi+0x2a] +4004c3: c3 ret diff --git a/listings/chap16/constant_propagation/constant_propagation.c b/listings/chap16/constant_propagation/constant_propagation.c new file mode 100755 index 0000000..251e07c --- /dev/null +++ b/listings/chap16/constant_propagation/constant_propagation.c @@ -0,0 +1,6 @@ +__attribute__((noinline)) +static int sum(int x, int y) { return x + y; } + +int main( int argc, char** argv ) { + return sum( 42, argc ); +} diff --git a/listings/chap16/cp_fact/cp_fact.asm b/listings/chap16/cp_fact/cp_fact.asm new file mode 100755 index 0000000..9ef2bd7 --- /dev/null +++ b/listings/chap16/cp_fact/cp_fact.asm @@ -0,0 +1,10 @@ +0000000000400450
: +400450: 48 83 ec 08 sub rsp,0x8 +400454: ba 18 00 00 00 mov edx,0x18 +400459: be 44 07 40 00 mov esi,0x400744 +40045e: bf 01 00 00 00 mov edi,0x1 +400463: 31 c0 xor eax,eax +400465: e8 c6 ff ff ff call 400430 <__printf_chk@plt> +40046a: 31 c0 xor eax,eax +40046c: 48 83 c4 08 add rsp,0x8 +400470: c3 ret diff --git a/listings/chap16/cp_fact/cp_fact.c b/listings/chap16/cp_fact/cp_fact.c new file mode 100755 index 0000000..ba4743b --- /dev/null +++ b/listings/chap16/cp_fact/cp_fact.c @@ -0,0 +1,12 @@ +#include + +int fact( int n ) { + if (n == 0) return 1; + else return n * fact( n-1 ); +} + +int main(void) { + printf("%d\n", fact( 4 ) ); + return 0; +} + diff --git a/listings/chap16/cycle_nonpar_arith/cycle_nonpar_arith.asm b/listings/chap16/cycle_nonpar_arith/cycle_nonpar_arith.asm new file mode 100755 index 0000000..04b42b1 --- /dev/null +++ b/listings/chap16/cycle_nonpar_arith/cycle_nonpar_arith.asm @@ -0,0 +1,14 @@ +looper: + mov rax,[rsi] + + ; The next instruction depends on the previous one. + ; It means that we can not swap them because + ; the program behavior will change. + xor rax, 0x1 + + ; One more dependency here + add [rdi],rax + add rsi,8 + add rdi,8 + dec rcx + jnz looper diff --git a/listings/chap16/cycle_par_arith/cycle_par_arith.asm b/listings/chap16/cycle_par_arith/cycle_par_arith.asm new file mode 100755 index 0000000..93a374c --- /dev/null +++ b/listings/chap16/cycle_par_arith/cycle_par_arith.asm @@ -0,0 +1,11 @@ +looper: +mov rax, [rsi] +mov rdx, [rsi + 8] +xor rax, 0x1 +xor rdx, 0x1 +add [rdi],rax +add [rdi+8],rdx +add rsi, 16 +add rdi, 16 +sub rcx, 2 +jnz looper diff --git a/listings/chap16/execution_time/execution_time.c b/listings/chap16/execution_time/execution_time.c new file mode 100755 index 0000000..2c760cc --- /dev/null +++ b/listings/chap16/execution_time/execution_time.c @@ -0,0 +1,25 @@ +#include +#include +#include +#include +#include + +int main(void) { + struct rusage r; + struct timeval start; + struct timeval end; + + getrusage(RUSAGE_SELF, &r ); + start = r.ru_utime; + + for( uint64_t i = 0; i < 100000000; i++ ); + + getrusage(RUSAGE_SELF, &r ); + end = r.ru_utime; + + long res = ((end.tv_sec - start.tv_sec) * 1000000L) + + end.tv_usec - start.tv_usec; + + printf( "Time elapsed in microseconds: %ld\n", res ); + return 0; +} diff --git a/listings/chap16/factorial_nontailrec/factorial_nontailrec.c b/listings/chap16/factorial_nontailrec/factorial_nontailrec.c new file mode 100755 index 0000000..3bf109b --- /dev/null +++ b/listings/chap16/factorial_nontailrec/factorial_nontailrec.c @@ -0,0 +1,7 @@ +__attribute__(( noinline )) + int factorial( int arg ) { + if ( arg == 0 ) return acc; + return arg * factorial( arg-1 ); + } + +int main(int argc, char** argv) { return factorial(argc); } diff --git a/listings/chap16/factorial_tailrec/factorial_tailrec.asm b/listings/chap16/factorial_tailrec/factorial_tailrec.asm new file mode 100755 index 0000000..a89dc91 --- /dev/null +++ b/listings/chap16/factorial_tailrec/factorial_tailrec.asm @@ -0,0 +1,8 @@ +00000000004004c6 : +4004c6: 89 f8 mov eax,edi +4004c8: 85 f6 test esi,esi +4004ca: 74 07 je 4004d3 +4004cc: 0f af c6 imul eax,esi +4004cf: ff ce dec esi +4004d1: eb f5 jmp 4004c8 +4004d3: c3 ret diff --git a/listings/chap16/factorial_tailrec/factorial_tailrec.c b/listings/chap16/factorial_tailrec/factorial_tailrec.c new file mode 100755 index 0000000..7557bef --- /dev/null +++ b/listings/chap16/factorial_tailrec/factorial_tailrec.c @@ -0,0 +1,9 @@ + +__attribute__(( noinline )) + int factorial( int acc, int arg ) { + if ( arg == 0 ) return acc; + return factorial( acc * arg, arg-1 ); + } + +int main(int argc, char** argv) { return factorial(1, argc); } + diff --git a/listings/chap16/image_sepia_c_example/image_sepia_c_example.c b/listings/chap16/image_sepia_c_example/image_sepia_c_example.c new file mode 100755 index 0000000..6f8ca0a --- /dev/null +++ b/listings/chap16/image_sepia_c_example/image_sepia_c_example.c @@ -0,0 +1,38 @@ +#include +struct pixel { uint8_t b, g, r; }; + +struct image { + uint32_t width, height; + struct pixel* array; +}; + +static unsigned char sat( uint64_t x) { + if (x < 256) return x; return 255; +} + +static void sepia_one( struct pixel* const pixel ) { + static const float c[3][3] = { + { .393f, .769f, .189f }, + { .349f, .686f, .168f }, + { .272f, .543f, .131f } }; + struct pixel const old = *pixel; + + pixel->r = sat( + old.r * c[0][0] + old.g * c[0][1] + old.b * c[0][2] + ); + pixel->g = sat( + old.r * c[1][0] + old.g * c[1][1] + old.b * c[1][2] + ); + pixel->b = sat( + old.r * c[2][0] + old.g * c[2][1] + old.b * c[2][2] + ); +} + +void sepia_c_inplace( struct image* img ) { + uint32_t x,y; + for( y = 0; y < img->height; y++ ) + for( x = 0; x < img->width; x++ ) + sepia_one( pixel_of( *img, x, y ) ); +} + + diff --git a/listings/chap16/matrix_init_linear/matrix_init_linear.c b/listings/chap16/matrix_init_linear/matrix_init_linear.c new file mode 100755 index 0000000..b571b73 --- /dev/null +++ b/listings/chap16/matrix_init_linear/matrix_init_linear.c @@ -0,0 +1,13 @@ +#include +#include +#define DIM (16*1024) + +int main( int argc, char** argv ) { + size_t i, j; + int* mat = (int*)malloc( DIM * DIM * sizeof( int ) ); + for( i = 0; i < DIM; ++i ) + for( j = 0; j < DIM; ++j ) + mat[i*DIM+j] = 42; + puts("TEST DONE"); + return 0; +} diff --git a/listings/chap16/matrix_init_ra/matrix_init_ra.c b/listings/chap16/matrix_init_ra/matrix_init_ra.c new file mode 100755 index 0000000..d963174 --- /dev/null +++ b/listings/chap16/matrix_init_ra/matrix_init_ra.c @@ -0,0 +1,13 @@ +#include +#include +#define DIM (16*1024) + +int main( int argc, char** argv ) { + size_t i, j; + int* mat = (int*)malloc( DIM * DIM * sizeof( int ) ); + for( i = 0; i < DIM; ++i ) + for( j = 0; j < DIM; ++j ) + mat[j*DIM+i] = 42; + puts("TEST DONE"); + return 0; +} diff --git a/listings/chap16/nrvo/nrvo.c b/listings/chap16/nrvo/nrvo.c new file mode 100755 index 0000000..9be8ea0 --- /dev/null +++ b/listings/chap16/nrvo/nrvo.c @@ -0,0 +1,19 @@ +struct p { + long x; + long y; + long z; +}; + +__attribute__((noinline)) + struct p f(void) { + struct p copy; + copy.x = 1; + copy.y = 2; + copy.z = 3; + return copy; + } + +int main(int argc, char** argv) { + volatile struct p inst = f(); + return 0; +} diff --git a/listings/chap16/nrvo_off/nrvo_off.asm b/listings/chap16/nrvo_off/nrvo_off.asm new file mode 100755 index 0000000..a21720b --- /dev/null +++ b/listings/chap16/nrvo_off/nrvo_off.asm @@ -0,0 +1,45 @@ +00000000004004b6 : +; prologue +4004b6: 55 push rbp +4004b7: 48 89 e5 mov rbp,rsp +; A hidden argument is the address of a structure which will hold the result. +; It is saved into stack. +4004ba: 48 89 7d d8 mov QWORD PTR [rbp-0x28],rdi +; Filling the fields of `copy` local variable +4004be: 48 c7 45 e0 01 00 00 mov QWORD PTR [rbp-0x20],0x1 +4004c5: 00 +4004c6: 48 c7 45 e8 02 00 00 mov QWORD PTR [rbp-0x18],0x2 +4004cd: 00 +4004ce: 48 c7 45 f0 03 00 00 mov QWORD PTR [rbp-0x10],0x3 +4004d5: 00 +; rax = address of the destination struct +4004d6: 48 8b 45 d8 mov rax,QWORD PTR [rbp-0x28] +; [rax] = 1 (taken from `copy.x`) +4004da: 48 8b 55 e0 mov rdx,QWORD PTR [rbp-0x20] +4004de: 48 89 10 mov QWORD PTR [rax],rdx +; [rax + 8] = 2 (taken from `copy.y`) +4004da: 48 8b 55 e0 mov rdx,QWORD PTR [rbp-0x20] +4004e1: 48 8b 55 e8 mov rdx,QWORD PTR [rbp-0x18] +4004e5: 48 89 50 08 mov QWORD PTR [rax+0x8],rdx +; [rax + 10] = 3 (taken from `copy.z`) +4004e9: 48 8b 55 f0 mov rdx,QWORD PTR [rbp-0x10] +4004ed: 48 89 50 10 mov QWORD PTR [rax+0x10],rdx +; rax = address where we have put the structure contents +; (it was the hidden argument) +4004f1: 48 8b 45 d8 mov rax,QWORD PTR [rbp-0x28] +4004f5: 5d pop rbp +4004f6: c3 ret + +00000000004004f7
: +4004f7: 55 push rbp +4004f8: 48 89 e5 mov rbp,rsp +4004fb: 48 83 ec 30 sub rsp,0x30 +4004ff: 89 7d dc mov DWORD PTR [rbp-0x24],edi +400502: 48 89 75 d0 mov QWORD PTR [rbp-0x30],rsi +400506: 48 8d 45 e0 lea rax,[rbp-0x20] +40050a: 48 89 c7 mov rdi,rax +40050d: e8 a4 ff ff ff call 4004b6 +400512: b8 00 00 00 00 mov eax,0x0 +400517: c9 leave +400518: c3 ret +400519: 0f 1f 80 00 00 00 00 nop DWORD PTR [rax+0x0] diff --git a/listings/chap16/nrvo_on/nrvo_on.asm b/listings/chap16/nrvo_on/nrvo_on.asm new file mode 100755 index 0000000..6f71cfc --- /dev/null +++ b/listings/chap16/nrvo_on/nrvo_on.asm @@ -0,0 +1,18 @@ +00000000004004b6 : +4004b6: 48 89 f8 mov rax,rdi +4004b9: 48 c7 07 01 00 00 00 mov QWORD PTR [rdi],0x1 +4004c0: 48 c7 47 08 02 00 00 mov QWORD PTR [rdi+0x8],0x2 +4004c7: 00 +4004c8: 48 c7 47 10 03 00 00 mov QWORD PTR [rdi+0x10],0x3 +4004cf: 00 +4004d0: c3 ret + +00000000004004d1
: +4004d1: 48 83 ec 20 sub rsp,0x20 +4004d5: 48 89 e7 mov rdi,rsp +4004d8: e8 d9 ff ff ff call 4004b6 +4004dd: b8 00 00 00 00 mov eax,0x0 +4004e2: 48 83 c4 20 add rsp,0x20 +4004e6: c3 ret +4004e7: 66 0f 1f 84 00 00 00 nop WORD PTR [rax+rax*1+0x0] +4004ee: 00 00 diff --git a/listings/chap16/prefetch_binsearch/prefetch_binsearch.c b/listings/chap16/prefetch_binsearch/prefetch_binsearch.c new file mode 100755 index 0000000..83f594f --- /dev/null +++ b/listings/chap16/prefetch_binsearch/prefetch_binsearch.c @@ -0,0 +1,46 @@ +#include +#include +#include + +#define SIZE 1024*512*16 + +int binarySearch(int *array, size_t number_of_elements, int key) { + size_t low = 0, high = number_of_elements-1, mid; + while(low <= high) { + mid = (low + high)/2; +#ifdef DO_PREFETCH + // low path + __builtin_prefetch (&array[(mid + 1 + high)/2], 0, 1); + // high path + __builtin_prefetch (&array[(low + mid - 1)/2], 0, 1); +#endif + + if(array[mid] < key) + low = mid + 1; + else if(array[mid] == key) + return mid; + else if(array[mid] > key) + high = mid-1; + } + return -1; +} + +int main() { + size_t i = 0; + int NUM_LOOKUPS = SIZE; + int *array; + int *lookups; + + + srand(time(NULL)); + array = malloc(SIZE*sizeof(int)); + lookups = malloc(NUM_LOOKUPS * sizeof(int)); + + for (i=0;i +#include + +void sse( float[static 4], float[static 4] ); + +int main() { + float x[4] = {1.0f, 2.0f, 3.0f, 4.0f }; + float y[4] = {5.0f, 6.0f, 7.0f, 8.0f }; + + sse( x, y ); + + printf( "%f %f %f %f\n", x[0], x[1], x[2], x[3] ); + return 0; +} diff --git a/listings/chap16/stack_unwind/stack_unwind.asm b/listings/chap16/stack_unwind/stack_unwind.asm new file mode 100755 index 0000000..f0efb3d --- /dev/null +++ b/listings/chap16/stack_unwind/stack_unwind.asm @@ -0,0 +1,26 @@ +extern printf +global unwind + +section .rodata +format : db "%x ", 10, 0 + +section .code +unwind: +push rbx + +; while (rbx != 0) { + ; print rbx; rbx = [rbx]; + ; } + mov rbx, rbp + .loop: + test rbx, rbx + jz .end + mov rdi, format + mov rsi, rbx + call printf + mov rbx, [rbx] + jmp .loop + + .end: + pop rbx + ret diff --git a/listings/chap16/stack_unwind/stack_unwind.c b/listings/chap16/stack_unwind/stack_unwind.c new file mode 100755 index 0000000..f028e40 --- /dev/null +++ b/listings/chap16/stack_unwind/stack_unwind.c @@ -0,0 +1,7 @@ +void unwind(); +void f( int count ) { + if ( count ) f( count-1 ); else unwind(); +} +int main(void) { + f( 10 ); return 0; +} diff --git a/listings/chap16/tail_rec_example_list/tail_rec_example_list.asm b/listings/chap16/tail_rec_example_list/tail_rec_example_list.asm new file mode 100755 index 0000000..754c888 --- /dev/null +++ b/listings/chap16/tail_rec_example_list/tail_rec_example_list.asm @@ -0,0 +1,10 @@ +0000000000400596 : +400596: 48 89 f8 mov rax,rdi +400599: 48 85 f6 test rsi,rsi +40059c: 74 0d je 4005ab +40059e: 48 85 c0 test rax,rax +4005a1: 74 08 je 4005ab +4005a3: 48 ff ce dec rsi +4005a6: 48 8b 00 mov rax,QWORD PTR [rax] +4005a9: eb ee jmp 400599 +4005ab: c3 ret diff --git a/listings/chap16/tail_rec_example_list/tail_rec_example_list.c b/listings/chap16/tail_rec_example_list/tail_rec_example_list.c new file mode 100755 index 0000000..0375cf2 --- /dev/null +++ b/listings/chap16/tail_rec_example_list/tail_rec_example_list.c @@ -0,0 +1,26 @@ +#include +#include + +struct llist { + struct llist* next; + int value; +}; + +struct llist* llist_at( + struct llist* lst, + size_t idx ) { + if ( lst && idx ) return llist_at( lst->next, idx-1 ); + return lst; +} +struct llist* c( int value, struct llist* next) { + struct llist* lst = malloc( sizeof(struct llist*) ); + lst->next = next; + lst->value = value; + return lst; +} + +int main( void ) { + struct llist* lst = c( 1, c( 2, c( 3, NULL ))); + printf("%d\n", llist_at( lst, 2 )->value ); + return 0; +} diff --git a/listings/chap17/cas_counter/cas_counter.c b/listings/chap17/cas_counter/cas_counter.c new file mode 100755 index 0000000..1baa700 --- /dev/null +++ b/listings/chap17/cas_counter/cas_counter.c @@ -0,0 +1,9 @@ +int add(int* p, int add ) { + bool done = false; + int value; + while (!done) { + value = *p + done = cas(p, value, value + add ); + } + return value + add; +} diff --git a/listings/chap17/condvar_mwe/condvar_mwe.c b/listings/chap17/condvar_mwe/condvar_mwe.c new file mode 100755 index 0000000..96988a5 --- /dev/null +++ b/listings/chap17/condvar_mwe/condvar_mwe.c @@ -0,0 +1,47 @@ +#include +#include +#include +#include + +pthread_cond_t condvar = PTHREAD_COND_INITIALIZER; +pthread_mutex_t m; + +bool sent = false; +void* t1_impl( void* _ ) { + pthread_mutex_lock( &m ); + puts( "Thread2 before wait" ); + + while (!sent) + pthread_cond_wait( &condvar, &m ); + + puts( "Thread2 after wait" ); + pthread_mutex_unlock( &m ); + return NULL; +} + +void* t2_impl( void* _ ) { + pthread_mutex_lock( &m ); + puts( "Thread1 before signal" ); + + sent = true; + pthread_cond_signal( &condvar ); + + puts( "Thread1 after signal" ); + pthread_mutex_unlock( &m ); + return NULL; +} + +int main( void ) { + pthread_t t1, t2; + + pthread_mutex_init( &m, NULL ); + pthread_create( &t1, NULL, t1_impl, NULL ); + sleep( 2 ); + pthread_create( &t2, NULL, t2_impl, NULL ); + + pthread_join( t1, NULL ); + pthread_join( t2, NULL ); + + pthread_mutex_destroy( &m ); + return 0; +} diff --git a/listings/chap17/deadlock_ex/deadlock_ex b/listings/chap17/deadlock_ex/deadlock_ex new file mode 100755 index 0000000..5740658 --- /dev/null +++ b/listings/chap17/deadlock_ex/deadlock_ex @@ -0,0 +1,15 @@ +mutex A, B; + +thread1 () { + lock(A); + lock(B); + unlock(B); + unlock(A); +} + +thread2() { + lock(B); + lock(A); + unlock(A); + unlock(B); +} diff --git a/listings/chap17/dist_fact_mp/dist_fact_mp.c b/listings/chap17/dist_fact_mp/dist_fact_mp.c new file mode 100755 index 0000000..2fa0a60 --- /dev/null +++ b/listings/chap17/dist_fact_mp/dist_fact_mp.c @@ -0,0 +1,60 @@ +#include +#include +#include +#include +#include + +#define THREADS 4 + +struct fact_task { + uint64_t num; + uint64_t from, to; + uint64_t result; +}; + +void* fact_worker( void* arg ) { + struct fact_task* const task = arg; + task-> result = 0; + for( uint64_t i = task-> from; i < task-> to; i++ ) + if ( task->num % i == 0 ) task-> result ++; + return NULL; +} + +/* assuming threads_count < num */ +uint64_t factors_mp( uint64_t num, size_t threads_count ) { + + struct fact_task* tasks = malloc( threads_count * sizeof( *tasks ) ); + pthread_t* threads = malloc( threads_count * sizeof( *threads ) ); + + uint64_t start = 1; + size_t step = num / threads_count; + + for( size_t i = 0; i < threads_count; i++ ) { + tasks[i].num = num; + tasks[i].from = start; + tasks[i].to = start + step; + start += step; + } + tasks[threads_count-1].to = num+1; + + for ( size_t i = 0; i < threads_count; i++ ) + pthread_create( threads + i, NULL, fact_worker, tasks + i ); + + uint64_t result = 0; + for ( size_t i = 0; i < threads_count; i++ ) { + pthread_join( threads[i], NULL ); + result += tasks[i].result; + } + + free( tasks ); + free( threads ); + return result; +} + + +int main( void ) { + uint64_t input = 2000000000; + printf( "Factors of %"PRIu64": %"PRIu64"\n", + input, factors_mp(input, THREADS ) ); + return 0; +} diff --git a/listings/chap17/dist_fact_mp_simple/dist_fact_mp_simple.c b/listings/chap17/dist_fact_mp_simple/dist_fact_mp_simple.c new file mode 100755 index 0000000..a10a5b9 --- /dev/null +++ b/listings/chap17/dist_fact_mp_simple/dist_fact_mp_simple.c @@ -0,0 +1,41 @@ +#include +#include +#include + +int input = 0; + +int result1 = 0; +void* fact_worker1( void* arg ) { + result1 = 0; + for( uint64_t i = 1; i < input/2; i++ ) + if ( input % i == 0 ) result1++; + return NULL; +} + +int result2 = 0; +void* fact_worker2( void* arg ) { + result2 = 0; + for( uint64_t i = input/2; i <= input; i++ ) + if ( input % i == 0 ) result2++; + return NULL; +} + +uint64_t factors_mp( uint64_t num ) { + input = num; + pthread_t thread1, thread2; + + pthread_create( &thread1, NULL, fact_worker1, NULL ); + pthread_create( &thread2, NULL, fact_worker2, NULL ); + + pthread_join( thread1, NULL ); + pthread_join( thread2, NULL ); + + return result1 + result2; +} + +int main( void ) { + uint64_t input = 2000000000; + printf( "Factors of %"PRIu64": %"PRIu64"\n", + input, factors_mp(input )); + return 0; +} diff --git a/listings/chap17/dist_fact_sp/dist_fact_sp.c b/listings/chap17/dist_fact_sp/dist_fact_sp.c new file mode 100755 index 0000000..5f15514 --- /dev/null +++ b/listings/chap17/dist_fact_sp/dist_fact_sp.c @@ -0,0 +1,20 @@ +#include +#include +#include +#include +#include + +uint64_t factors( uint64_t num ) { + uint64_t result = 0; + for (uint64_t i = 1; i <= num; i++ ) + if ( num % i == 0 ) result++; + return result; +} + +int main( void ) { + /* volatile to prevent constant propagation */ + volatile uint64_t input = 2000000000; + + printf( "Factors of %"PRIu64": %"PRIu64"\n", input, factors(input) ); + return 0; +} diff --git a/listings/chap17/ex_locality_asm1/ex_locality_asm1.asm b/listings/chap17/ex_locality_asm1/ex_locality_asm1.asm new file mode 100755 index 0000000..90222c2 --- /dev/null +++ b/listings/chap17/ex_locality_asm1/ex_locality_asm1.asm @@ -0,0 +1,12 @@ +mov al,[rsi + 4] +mov [rdi+4],al + +mov al,[rsi + 10004] +mov [rdi+10004],al + + +mov al,[rsi + 5] +mov [rdi+5],al + +mov al,[rsi + 10005] +mov [rdi+10005],al diff --git a/listings/chap17/ex_locality_asm2/ex_locality_asm2.asm b/listings/chap17/ex_locality_asm2/ex_locality_asm2.asm new file mode 100755 index 0000000..3385d3d --- /dev/null +++ b/listings/chap17/ex_locality_asm2/ex_locality_asm2.asm @@ -0,0 +1,10 @@ +mov al,[rsi + 4] +mov [rdi+4],al +mov al,[rsi + 5] +mov [rdi+5],al + +mov al,[rsi + 10004] +mov [rdi+10004],al + +mov al,[rsi + 10005] +mov [rdi+10005],al diff --git a/listings/chap17/ex_locality_src/ex_locality_src.c b/listings/chap17/ex_locality_src/ex_locality_src.c new file mode 100755 index 0000000..c785a7e --- /dev/null +++ b/listings/chap17/ex_locality_src/ex_locality_src.c @@ -0,0 +1,7 @@ +char x[1000000], y[1000000]; +... +x[4] = y[4]; +x[10004] = y[10004]; + +x[5] = y[5]; +x[10005] = y[10005]; diff --git a/listings/chap17/livelock_ex/livelock_ex b/listings/chap17/livelock_ex/livelock_ex new file mode 100755 index 0000000..ffb4bc8 --- /dev/null +++ b/listings/chap17/livelock_ex/livelock_ex @@ -0,0 +1,21 @@ +mutex m1, m2; + +thread1() { + lock( m1 ); + while ( mutex_trylock m2 indicates LOCKED ) { + unlock( m1 ); + wait for some time; + lock( m1 ); + } + // now we are good because both locks are taken +} + +thread2() { + lock( m2 ); + while ( mutex_trylock m1 indicates LOCKED ) { + unlock( m2 ); + wait for some time; + lock( m2 ); + } + // now we are good because both locks are taken +} diff --git a/listings/chap17/mem_reorder_sample/mem_reorder_sample b/listings/chap17/mem_reorder_sample/mem_reorder_sample new file mode 100755 index 0000000..147a710 --- /dev/null +++ b/listings/chap17/mem_reorder_sample/mem_reorder_sample @@ -0,0 +1,13 @@ +x = 0; +y = 0; + +thread1() { + x = 1; + load y +} + +thread2() { + y = 1; + load x +} + diff --git a/listings/chap17/mem_reorder_sample/mem_reorder_sample.c b/listings/chap17/mem_reorder_sample/mem_reorder_sample.c new file mode 100755 index 0000000..f9d7b79 --- /dev/null +++ b/listings/chap17/mem_reorder_sample/mem_reorder_sample.c @@ -0,0 +1,12 @@ +int x = 0; +int y = 0; + +void thread1(void) { + x = 1; + print(y); +} + +void thread2(void) { + y = 1; + print(x); +} diff --git a/listings/chap17/mem_reorder_sample_happened/mem_reorder_sample_happened b/listings/chap17/mem_reorder_sample_happened/mem_reorder_sample_happened new file mode 100755 index 0000000..0780c61 --- /dev/null +++ b/listings/chap17/mem_reorder_sample_happened/mem_reorder_sample_happened @@ -0,0 +1,12 @@ +x = 0; +y = 0; + +proc1() { + load y + x = 1; +} + +proc2() { + load x + y = 1; +} diff --git a/listings/chap17/mem_reorder_sample_happened/mem_reorder_sample_happened.c b/listings/chap17/mem_reorder_sample_happened/mem_reorder_sample_happened.c new file mode 100755 index 0000000..559050b --- /dev/null +++ b/listings/chap17/mem_reorder_sample_happened/mem_reorder_sample_happened.c @@ -0,0 +1,12 @@ +int x = 0; +int y = 0; + +void thread1(void) { + print(y); + x = 1; +} + +void thread2(void) { + print(x); + y = 1; +} diff --git a/listings/chap17/mutex_ex1/mutex_ex1.c b/listings/chap17/mutex_ex1/mutex_ex1.c new file mode 100755 index 0000000..917849c --- /dev/null +++ b/listings/chap17/mutex_ex1/mutex_ex1.c @@ -0,0 +1,48 @@ +#include +#include +#include +#include + +pthread_mutex_t m; + +pthread_t t1, t2; + +uint64_t value = 0; + +void* impl1( void* _ ) { + for (int n = 0; n < 1000000000; n++) { + pthread_mutex_lock( &m ); + value += 1; + pthread_mutex_unlock( &m ); + } + return NULL; +} + +void* impl2( void* _ ) { + for (int n = 0; n < 10; n++) { + + pthread_mutex_lock( &m ); + + printf("%" PRIu64 "\n", value ); + + sleep(1); + value++; + printf("%" PRIu64 "\n\n", value ); + + pthread_mutex_unlock( &m ); + sleep(1); + } + return NULL; +} + +int main(void) { + pthread_mutex_init( &m, NULL ); + pthread_create( &t1, NULL, impl1, NULL ); + pthread_create( &t2, NULL, impl2, NULL ); + + pthread_join( t1, NULL ); + pthread_join( t2, NULL ); + + pthread_mutex_destroy( &m ); + return 0; +} diff --git a/listings/chap17/mutex_ex_counter_bad/mutex_ex_counter_bad.c b/listings/chap17/mutex_ex_counter_bad/mutex_ex_counter_bad.c new file mode 100755 index 0000000..12f8eeb --- /dev/null +++ b/listings/chap17/mutex_ex_counter_bad/mutex_ex_counter_bad.c @@ -0,0 +1,25 @@ +#include +#include +#include +#include + +pthread_t t1, t2; + +uint64_t value = 0; + +void* impl1( void* _ ) { + for (int n = 0; n < 10000000; n++) { + value += 1; + } + return NULL; +} + +int main(void) { + pthread_create( &t1, NULL, impl1, NULL ); + pthread_create( &t2, NULL, impl1, NULL ); + + pthread_join( t1, NULL ); + pthread_join( t2, NULL ); + printf( "%"PRIu64"\n", value ); + return 0; +} diff --git a/listings/chap17/mutex_ex_counter_good/mutex_ex_counter_good.c b/listings/chap17/mutex_ex_counter_good/mutex_ex_counter_good.c new file mode 100755 index 0000000..59e834b --- /dev/null +++ b/listings/chap17/mutex_ex_counter_good/mutex_ex_counter_good.c @@ -0,0 +1,35 @@ +#include +#include +#include +#include + +pthread_mutex_t m; // + +pthread_t t1, t2; + +uint64_t value = 0; + +void* impl1( void* _ ) { + for (int n = 0; n < 10000000; n++) { + pthread_mutex_lock( &m );// + + value += 1; + + pthread_mutex_unlock( &m );// + } + return NULL; +} + +int main(void) { + pthread_mutex_init( &m, NULL ); // + + pthread_create( &t1, NULL, impl1, NULL ); + pthread_create( &t2, NULL, impl1, NULL ); + + pthread_join( t1, NULL ); + pthread_join( t2, NULL ); + printf( "%"PRIu64"\n", value ); + + pthread_mutex_destroy( &m ); // + return 0; +} diff --git a/listings/chap17/pthread_create_mwe/pthread_create_mwe.c b/listings/chap17/pthread_create_mwe/pthread_create_mwe.c new file mode 100755 index 0000000..f2a78cb --- /dev/null +++ b/listings/chap17/pthread_create_mwe/pthread_create_mwe.c @@ -0,0 +1,20 @@ +#include +#include +#include + +void* threadimpl( void* arg ) { + for(int i = 0; i < 10; i++ ) { + puts( arg ); + sleep(1); + } + return NULL; +} + +int main( void ) { + pthread_t t1, t2; + pthread_create( &t1, NULL, threadimpl, "fizz" ); + pthread_create( &t2, NULL, threadimpl, "buzzzz" ); + pthread_exit( NULL ); + puts("bye"); + return 0; +} diff --git a/listings/chap17/pthread_create_mwe_out/pthread_create_mwe_out b/listings/chap17/pthread_create_mwe_out/pthread_create_mwe_out new file mode 100755 index 0000000..feab570 --- /dev/null +++ b/listings/chap17/pthread_create_mwe_out/pthread_create_mwe_out @@ -0,0 +1,21 @@ +> ./main +fizz +buzzzz +buzzzz +fizz +fizz +buzzzz +fizz +buzzzz +fizz +buzzzz +buzzzz +fizz +buzzzz +fizz +buzzzz +fizz +buzzzz +fizz +buzzzz +fizz diff --git a/listings/chap17/reordering_cpu_mwe/reordering_cpu_mwe.c b/listings/chap17/reordering_cpu_mwe/reordering_cpu_mwe.c new file mode 100755 index 0000000..5c78b25 --- /dev/null +++ b/listings/chap17/reordering_cpu_mwe/reordering_cpu_mwe.c @@ -0,0 +1,76 @@ +#include +#include +#include +#include +#include +#include +#include + +sem_t sem_begin0, sem_begin1, sem_end; + +int x, y, read0, read1; + +void *thread0_impl( void *param ) +{ + for (;;) { + + sem_wait( &sem_begin0 ); + + x = 1; + // This only disables compiler reorderings: + asm volatile("" ::: "memory"); + // The following line disables also hardware reorderings: + // asm volatile("mfence" ::: "memory"); + read0 = y; + + sem_post( &sem_end ); + } + return NULL; +}; + +void *thread1_impl( void *param ) +{ + for (;;) { + + sem_wait( &sem_begin1 ); + + y = 1; + // This only disables compiler reorderings: + asm volatile("" ::: "memory"); + // The following line disables also hardware reorderings + // asm volatile("mfence" ::: "memory"); + read1 = x; + + sem_post( &sem_end ); + } + return NULL; +}; + +int main( void ) { + + sem_init( &sem_begin0, 0, 0); + sem_init( &sem_begin1, 0, 0); + sem_init( &sem_end, 0, 0); + + pthread_t thread0, thread1; + pthread_create( &thread0, NULL, thread0_impl, NULL); + pthread_create( &thread1, NULL, thread1_impl, NULL); + + for (uint64_t i = 0; i < 100000; i++) + { + x = 0; + y = 0; + sem_post( &sem_begin0 ); + sem_post( &sem_begin1 ); + + sem_wait( &sem_end ); + sem_wait( &sem_end ); + + if (read0 == 0 && read1 == 0 ) { + printf( "reordering happened on iteration %" PRIu64 "\n", i ); + exit(0); + } + } + puts("No reordering detected during 100000 iterations"); + return 0; +} diff --git a/listings/chap17/semaphore_mwe/semaphore_mwe.c b/listings/chap17/semaphore_mwe/semaphore_mwe.c new file mode 100755 index 0000000..bae3329 --- /dev/null +++ b/listings/chap17/semaphore_mwe/semaphore_mwe.c @@ -0,0 +1,45 @@ +#include +#include +#include +#include +#include + +sem_t sem; + +uint64_t counter1 = 0; +uint64_t counter2 = 0; + +pthread_t t1, t2, t3; + +void* t1_impl( void* _ ) { + while( counter1 < 10000000 ) counter1++; + sem_post( &sem ); + return NULL; +} + +void* t2_impl( void* _ ) { + while( counter2 < 20000000 ) counter2++; + sem_post( &sem ); + return NULL; +} + +void* t3_impl( void* _ ) { + sem_wait( &sem ); + sem_wait( &sem ); + printf("End: counter1 = %" PRIu64 " counter2 = %" PRIu64 "\n", + counter1, counter2 ); + return NULL; +} + +int main(void) { + sem_init( &sem, 0, 0 ); + pthread_create( &t3, NULL, t3_impl, NULL ); + + sleep( 1 ); + pthread_create( &t1, NULL, t1_impl, NULL ); + pthread_create( &t2, NULL, t2_impl, NULL ); + + sem_destroy( &sem ); + pthread_exit( NULL ); + return 0; +} diff --git a/listings/chap17/thread_join_mwe/thread_join_mwe.c b/listings/chap17/thread_join_mwe/thread_join_mwe.c new file mode 100755 index 0000000..dbe05bf --- /dev/null +++ b/listings/chap17/thread_join_mwe/thread_join_mwe.c @@ -0,0 +1,22 @@ +#include +#include +#include + +void* worker( void* param ) { + for( int i = 0; i < 3; i++ ) { + puts( (const char*) param ); + sleep(1); + } + return (void*)"done"; +} + +int main( void ) { + + pthread_t t; + void* result; + + pthread_create( &t, NULL, worker, (void*) "I am a worker!" ); + pthread_join( t, &result ); + puts( (const char*) result ); + return 0; +} diff --git a/listings/chap2/addressing/addressing.asm b/listings/chap2/addressing/addressing.asm new file mode 100755 index 0000000..aaf6dce --- /dev/null +++ b/listings/chap2/addressing/addressing.asm @@ -0,0 +1,5 @@ +mov rax, [rbx + 4* rcx + 9] +mov rax, [4*r9] +mov rdx, [rax + rbx] +lea rax, [rbx + rbx * 4] ; rax = rbx * 5 +add r8, [9 + rbx*8 + 7] diff --git a/listings/chap2/data_decl/data_decl.asm b/listings/chap2/data_decl/data_decl.asm new file mode 100755 index 0000000..91bd953 --- /dev/null +++ b/listings/chap2/data_decl/data_decl.asm @@ -0,0 +1,4 @@ +section .data + example1: db 5, 16, 8, 4, 2, 1 + example2: times 999 db 42 + example3: dw 999 \ No newline at end of file diff --git a/listings/chap2/endianness/endianness.asm b/listings/chap2/endianness/endianness.asm new file mode 100755 index 0000000..5823588 --- /dev/null +++ b/listings/chap2/endianness/endianness.asm @@ -0,0 +1,59 @@ +section .data + +newline_char: db 10 +codes: db '0123456789abcdef' +global _start + + +print_newline: + mov rax, 1 + mov rdi, 1 + mov rsi, newline_char + mov rdx, 1 + push r10 + syscall + pop r10 + ret + +print_hex: + mov rax, rdi + + mov rdi, 1 + mov rdx, 1 + mov rcx, 64 +iterate: + push rax + sub rcx, 4 + sar rax, cl + and rax, 0xf + lea rsi, [codes + rax] + mov rax, 1 + + push rcx + syscall + pop rcx + + pop rax + test rcx, rcx + jnz iterate + + ret + +section .data +demo1: dq 0x1122334455667788 +demo2: db 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88 + +section .text + +_start: + mov rdi, [demo1] + call print_hex + call print_newline + + mov rdi, [demo2] + call print_hex + call print_newline + + mov rax, 60 + xor rdi, rdi + syscall diff --git a/listings/chap2/false/false.asm b/listings/chap2/false/false.asm new file mode 100755 index 0000000..b43e283 --- /dev/null +++ b/listings/chap2/false/false.asm @@ -0,0 +1,7 @@ +global _start + +section .text +_start: + mov rdi, 1 + mov rax, 60 + syscall diff --git a/listings/chap2/hello/hello.asm b/listings/chap2/hello/hello.asm new file mode 100755 index 0000000..2bda787 --- /dev/null +++ b/listings/chap2/hello/hello.asm @@ -0,0 +1,12 @@ +global _start + +section .data +message: db 'hello, world!', 10 + +section .text +_start: + mov rax, 1 ; system call number should be stored in rax + mov rdi, 1 ; argument #1 in rdi: where to write (descriptor)? + mov rsi, message ; argument #2 in rsi: where does the string start? + mov rdx, 14 ; argument #3 in rdx: how many bytes to write? + syscall ; this instruction invokes a system call diff --git a/listings/chap2/hello_proper_exit/hello_proper_exit.asm b/listings/chap2/hello_proper_exit/hello_proper_exit.asm new file mode 100755 index 0000000..d9923e0 --- /dev/null +++ b/listings/chap2/hello_proper_exit/hello_proper_exit.asm @@ -0,0 +1,17 @@ +section .data +message: db 'hello, world!', 10 + +section .text +global _start + +_start: + mov rax, 1 ; 'write' syscall number + mov rdi, 1 ; stdout descriptor + mov rsi, message ; string address + mov rdx, 14 ; string length in bytes + syscall + + mov rax, 60 ; 'exit' syscall number + xor rdi, rdi + syscall + diff --git a/listings/chap2/jumps/jumps.asm b/listings/chap2/jumps/jumps.asm new file mode 100755 index 0000000..228300c --- /dev/null +++ b/listings/chap2/jumps/jumps.asm @@ -0,0 +1,10 @@ +mov rax, -1 +mov rdx, 2 + +cmp rax, rdx +jg location +ja location ; different logic! + +cmp rax, rdx +je location ; if rax equals rdx +jne location ; if rax is not equal to rdx \ No newline at end of file diff --git a/listings/chap2/jumps_example/jumps_example.asm b/listings/chap2/jumps_example/jumps_example.asm new file mode 100755 index 0000000..33ba157 --- /dev/null +++ b/listings/chap2/jumps_example/jumps_example.asm @@ -0,0 +1,7 @@ + cmp rax, 42 + jl yes + mov rbx, 0 + jmp ex +yes: + mov rbx, 1 +ex: diff --git a/listings/chap2/lea_vs_mov/lea_vs_mov.asm b/listings/chap2/lea_vs_mov/lea_vs_mov.asm new file mode 100755 index 0000000..35b64c8 --- /dev/null +++ b/listings/chap2/lea_vs_mov/lea_vs_mov.asm @@ -0,0 +1,21 @@ +; rsi <- address of label 'codes', a number +mov rsi, codes + +; rsi <- memory contents starting at 'codes' address +; 8 consecutive bytes are taken because rsi is 8 bytes long +mov rsi, [codes] + +; rsi <- address of 'codes' +; in this case it is equivalent of mov rsi, codes +; in general the address can contain several components +lea rsi, [codes] + +; rsi <- memory contents starting at (codes+rax) +mov rsi, [codes + rax] + +; rsi <- codes + rax +; equivalent of combination: +; -- mov rsi, codes +; -- add rsi, rax +; Can't do it with a single mov! +lea rsi, [codes + rax] diff --git a/listings/chap2/print_call/print_call.asm b/listings/chap2/print_call/print_call.asm new file mode 100755 index 0000000..93fd355 --- /dev/null +++ b/listings/chap2/print_call/print_call.asm @@ -0,0 +1,52 @@ +section .data + +newline_char: db 10 +codes: db '0123456789abcdef' + +section .text +global _start + +print_newline: + mov rax, 1 ; 'write' syscall identifier + mov rdi, 1 ; stdout file descriptor + mov rsi, newline_char ; where do we take data from + mov rdx, 1 ; the amount of bytes to write + syscall + ret + +print_hex: + mov rax, rdi + + mov rdi, 1 + mov rdx, 1 + mov rcx, 64 ; how far are we shifting rax? +iterate: + push rax ; Save the initial rax value + sub rcx, 4 + sar rax, cl ; shift to 60, 56, 52, ... 4, 0 + ; the cl register is the smallest part of rcx + and rax, 0xf ; clear all bits but the lowest four + lea rsi, [codes + rax]; take a hexadecimal digit character code + + mov rax, 1 ; + + push rcx ; syscall will break rcx + syscall ; rax = 1 (31) -- the write identifier, + ; rdi = 1 for stdout, + ; rsi = the address of a character, see line 29 + pop rcx + + pop rax ; ^ see line 24 ^ + test rcx, rcx ; rcx = 0 when all digits are shown + jnz iterate + + ret + +_start: + mov rdi, 0x1122334455667788 + call print_hex + call print_newline + + mov rax, 60 + xor rdi, rdi + syscall diff --git a/listings/chap2/print_rax/print_rax.asm b/listings/chap2/print_rax/print_rax.asm new file mode 100755 index 0000000..94556fd --- /dev/null +++ b/listings/chap2/print_rax/print_rax.asm @@ -0,0 +1,42 @@ +section .data +codes: + db '0123456789ABCDEF' + +section .text +global _start +_start: + ; number 1122... in hexadecimal format + mov rax, 0x1122334455667788 + + mov rdi, 1 + mov rdx, 1 + mov rcx, 64 + ; Each 4 bits should be output as one hexadecimal digit + ; Use shift and bitwise AND to isolate them + ; the result is the offset in 'codes' array +.loop: + push rax + sub rcx, 4 + ; cl is a register, smallest part of rcx + ; rax -- eax -- ax -- ah + al + ; rcx -- ecx -- cx -- ch + cl + sar rax, cl + and rax, 0xf + + lea rsi, [codes + rax] + mov rax, 1 + + ; syscall leaves rcx and r11 changed + push rcx + syscall + pop rcx + + pop rax + ; test can be used for the fastest 'is it a zero?' check + ; see docs for 'test' command + test rcx, rcx + jnz .loop + + mov rax, 60 ; invoke 'exit' system call + xor rdi, rdi + syscall diff --git a/listings/chap2/strlen/strlen.asm b/listings/chap2/strlen/strlen.asm new file mode 100755 index 0000000..496e063 --- /dev/null +++ b/listings/chap2/strlen/strlen.asm @@ -0,0 +1,38 @@ +global _start + +section .data + +test_string: db "abcdef", 0 + +section .text + +strlen: ; by our convention, first and the only argument + ; is taken from rdi + xor rax, rax ; rax will hold string length. If it is not + ; zeroed first, its value will be totally random + +.loop: ; main loop starts here + cmp byte [rdi+rax], 0 ; Check if the current symbol is null-terminator. + ; We absolutely need that 'byte' modifier since + ; the left and the right part of cmp should be + ; of the same size. Right operand is immediate + ; and holds no information about its size, + ; hence we don't know how many bytes should be + ; taken from memory and compared to zero + je .end ; Jump if we found null-terminator + + inc rax ; Otherwise go to next symbol and increase + ; counter + jmp .loop + +.end: + ret ; When we hit 'ret', rax should hold return value + +_start: + + mov rdi, test_string + call strlen + mov rdi, rax + + mov rax, 60 + syscall diff --git a/listings/chap2/strlen_bug1/strlen_bug1.asm b/listings/chap2/strlen_bug1/strlen_bug1.asm new file mode 100755 index 0000000..0530666 --- /dev/null +++ b/listings/chap2/strlen_bug1/strlen_bug1.asm @@ -0,0 +1,25 @@ +global _start + +section .data + +test_string: db "abcdef", 0 + +section .text + +strlen: +.loop: + cmp byte [rdi+r13], 0 + je .end + inc r13 + jmp .loop +.end: + mov rax, r13 + ret + +_start: + mov rdi, test_string + call strlen + mov rdi, rax + + mov rax, 60 + syscall diff --git a/listings/chap3/gdt64/gdt64.asm b/listings/chap3/gdt64/gdt64.asm new file mode 100755 index 0000000..163c983 --- /dev/null +++ b/listings/chap3/gdt64/gdt64.asm @@ -0,0 +1,25 @@ +align 16 ; This ensures that the next command or data element is +; stored starting at an address divisible by 16 (even if we need +; to skip some bytes to achieve that). + +; The following will be copied to GDTR via LGDTR instruction: + +GDTR64: ; Global Descriptors Table Register + dw gdt64_end - gdt64 - 1 ; limit of GDT (size minus one) + dq 0x0000000000001000 ; linear address of GDT + + +; This structure is copied to 0x0000000000001000 +gdt64: +SYS64_NULL_SEL equ $-gdt64 ; Null Segment + dq 0x0000000000000000 +; Code segment, read/exec, nonconforming +SYS64_CODE_SEL equ $-gdt64 + dq 0x0020980000000000 ; 0x00209A0000000000 +; Data segment, read/write, expand down +SYS64_DATA_SEL equ $-gdt64 + dq 0x0000900000000000 ; 0x0020920000000000 +gdt64_end: + +; Dollar sign denotes the current memory address, so +; $-gdt64 means an offset from `gdt64` label in bytes diff --git a/listings/chap3/loader_start32/loader_start32.asm b/listings/chap3/loader_start32/loader_start32.asm new file mode 100755 index 0000000..1e685bf --- /dev/null +++ b/listings/chap3/loader_start32/loader_start32.asm @@ -0,0 +1,23 @@ + lgdt cs:[_gdtr] + + mov eax, cr0 ; !! Privileged instruction + or al, 1 ; this is the bit responsible for protected mode + mov cr0, eax ; !! Privileged instruction + + jmp (0x1 << 3):start32 ; assign first seg selector to cs + +align 16 +_gdtr: ; stores GDT's last entry index + GDT address +dw 47 +dq _gdt + +align 16 + +_gdt: +; Null descriptor (should be present in any GDT) +dd 0x00, 0x00 +; x32 code descriptor: +db 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x9A, 0xCF, 0x00 ; differ by exec bit +; x32 data descriptor: +db 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x92, 0xCF, 0x00 ; execution off (0x92) +; size size base base base util util|size base diff --git a/listings/chap3/risc_cisc/risc_cisc.asm b/listings/chap3/risc_cisc/risc_cisc.asm new file mode 100755 index 0000000..3444bc1 --- /dev/null +++ b/listings/chap3/risc_cisc/risc_cisc.asm @@ -0,0 +1,10 @@ +mov rax, 0x1111222233334444 ; rax = 0x1111222233334444 +mov eax, 0x55556666 ; !rax = 0x0000000055556666 + ; why not rax = 0x1122334455556666? + +mov rax, 0x1111222233334444 ; rax = 0x1111222233334444 +mov ax, 0x7777 ; rax = 0x1111222233337777 + ; this works as expected +mov rax, 0x1111222233334444 ; rax = 0x1111222233334444 +xor eax, eax ; rax = 0x0000000000000000 + ; why not rax = 0x1111222200000000? diff --git a/listings/chap4/mappings_loop/mappings_loop b/listings/chap4/mappings_loop/mappings_loop new file mode 100755 index 0000000..4e0269d --- /dev/null +++ b/listings/chap4/mappings_loop/mappings_loop @@ -0,0 +1,11 @@ +> nasm -felf64 -o main.o mappings_loop.asm +> ld -o main main.o +> ./main & +[1] 2186 +> cat /proc/2186/maps +00400000-00401000 r-xp 00000000 08:01 144225 /home/stud/main +00600000-00601000 rwxp 00000000 08:01 144225 /home/stud/main +7fff11ac0000-7fff11ae1000 rwxp 00000000 00:00 0 [stack] +7fff11bfc000-7fff11bfe000 r-xp 00000000 00:00 0 [vdso] +7fff11bfe000-7fff11c00000 r--p 00000000 00:00 0 [vvar] +ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall] diff --git a/listings/chap4/mappings_loop/mappings_loop.asm b/listings/chap4/mappings_loop/mappings_loop.asm new file mode 100755 index 0000000..0d7ad91 --- /dev/null +++ b/listings/chap4/mappings_loop/mappings_loop.asm @@ -0,0 +1,7 @@ +section .data +correct: dq -1 +section .text + +global _start +_start: +jmp _start diff --git a/listings/chap4/mmap/mmap.asm b/listings/chap4/mmap/mmap.asm new file mode 100755 index 0000000..0df846f --- /dev/null +++ b/listings/chap4/mmap/mmap.asm @@ -0,0 +1,66 @@ +; These macrodefinitions are copied from linux sources +; Linux is written in C, so the definitions looked a bit +; different there. +; We could have just looked up their values and use +; them directly in right places +; However it would have made the code much less legible + +%define O_RDONLY 0 +%define PROT_READ 0x1 +%define MAP_PRIVATE 0x2 + +section .data +; This is the file name. You are free to change it. +fname: db 'test.txt', 0 + +section .text +global _start + +; These functions are used to print a null terminated string +print_string: + push rdi + call string_length + pop rsi + mov rdx, rax + mov rax, 1 + mov rdi, 1 + syscall + ret +string_length: + xor rax, rax +.loop: + cmp byte [rdi+rax], 0 + je .end + inc rax + jmp .loop +.end: + ret + +_start: +; call open +mov rax, 2 +mov rdi, fname +mov rsi, O_RDONLY ; Open file read only +mov rdx, 0 ; We are not creating a file + ; so this argument has no meaning +syscall + +; mmap +mov r8, rax ; rax holds opened file descriptor + ; it is the fourth argument of mmap +mov rax, 9 ; mmap number +mov rdi, 0 ; operating system will choose mapping destination +mov rsi, 4096 ; page size +mov rdx, PROT_READ ; new memory region will be marked read only +mov r10, MAP_PRIVATE ; pages will not be shared + +mov r9, 0 ; offset inside test.txt +syscall ; now rax will point to mapped location + +mov rdi, rax +call print_string + +mov rax, 60 ; use exit system call to shut down correctly +xor rdi, rdi +syscall + diff --git a/listings/chap4/segfault_badaddr/segfault_badaddr.asm b/listings/chap4/segfault_badaddr/segfault_badaddr.asm new file mode 100755 index 0000000..20bc8b2 --- /dev/null +++ b/listings/chap4/segfault_badaddr/segfault_badaddr.asm @@ -0,0 +1,11 @@ +section .data +correct: dq -1 +section .text +global _start +_start: +mov rax, [0x400000-1] + +; exit +mov rax, 60 +xor rdi, rdi +syscall diff --git a/listings/chap4/segfault_readonly/segfault_readonly.asm b/listings/chap4/segfault_readonly/segfault_readonly.asm new file mode 100755 index 0000000..1d0e281 --- /dev/null +++ b/listings/chap4/segfault_readonly/segfault_readonly.asm @@ -0,0 +1,14 @@ +section .data +correct: dq -1 +section .text +global _start +_start: +jmp _start +mov rbx, correct +sub rbx, 64 * 1024 +mov rbx, [rbx] + +; exit +mov rax, 60 +xor rdi, rdi +syscall diff --git a/listings/chap5/cat_elfheader/cat_elfheader b/listings/chap5/cat_elfheader/cat_elfheader new file mode 100755 index 0000000..752808a --- /dev/null +++ b/listings/chap5/cat_elfheader/cat_elfheader @@ -0,0 +1,39 @@ + +Elf file type is EXEC (Executable file) +Entry point 0x4025a6 +There are 9 program headers, starting at offset 64 + +Program Headers: + Type Offset VirtAddr PhysAddr + FileSiz MemSiz Flags Align + PHDR 0x0000000000000040 0x0000000000400040 0x0000000000400040 + 0x00000000000001f8 0x00000000000001f8 R E 8 + INTERP 0x0000000000000238 0x0000000000400238 0x0000000000400238 + 0x000000000000001c 0x000000000000001c R 1 + [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2] + LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000 + 0x000000000000b1ec 0x000000000000b1ec R E 200000 + LOAD 0x000000000000be10 0x000000000060be10 0x000000000060be10 + 0x0000000000000504 0x0000000000000ef8 RW 200000 + DYNAMIC 0x000000000000be28 0x000000000060be28 0x000000000060be28 + 0x00000000000001d0 0x00000000000001d0 RW 8 + NOTE 0x0000000000000254 0x0000000000400254 0x0000000000400254 + 0x0000000000000044 0x0000000000000044 R 4 + GNU_EH_FRAME 0x0000000000009e14 0x0000000000409e14 0x0000000000409e14 + 0x000000000000030c 0x000000000000030c R 4 + GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000 + 0x0000000000000000 0x0000000000000000 RW 10 + GNU_RELRO 0x000000000000be10 0x000000000060be10 0x000000000060be10 + 0x00000000000001f0 0x00000000000001f0 R 1 + + Section to Segment mapping: + Segment Sections... + 00 + 01 .interp + 02 .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame + 03 .init_array .fini_array .jcr .dynamic .got .got.plt .data .bss + 04 .dynamic + 05 .note.ABI-tag .note.gnu.build-id + 06 .eh_frame_hdr + 07 + 08 .init_array .fini_array .jcr .dynamic .got diff --git a/listings/chap5/define_cat_count/define_cat_count.asm b/listings/chap5/define_cat_count/define_cat_count.asm new file mode 100755 index 0000000..8f47135 --- /dev/null +++ b/listings/chap5/define_cat_count/define_cat_count.asm @@ -0,0 +1,4 @@ +%define cat_count 42 + + +mov rax, cat_count diff --git a/listings/chap5/define_cat_count_preprocessed/define_cat_count_preprocessed.asm b/listings/chap5/define_cat_count_preprocessed/define_cat_count_preprocessed.asm new file mode 100755 index 0000000..e33c811 --- /dev/null +++ b/listings/chap5/define_cat_count_preprocessed/define_cat_count_preprocessed.asm @@ -0,0 +1,4 @@ +%line 2+1 define_cat_count.asm + + +mov rax, 42 diff --git a/listings/chap5/defines/defines.asm b/listings/chap5/defines/defines.asm new file mode 100755 index 0000000..2de3bcc --- /dev/null +++ b/listings/chap5/defines/defines.asm @@ -0,0 +1,16 @@ +%define i 1 + +%define d i * 3 +%xdefine xd i * 3 +%assign a i * 3 + + +mov rax, d +mov rax, xd +mov rax, a + +; let's redefine i +%define i 100 +mov rax, d +mov rax, xd +mov rax, a diff --git a/listings/chap5/defines_preprocessed/defines_preprocessed.asm b/listings/chap5/defines_preprocessed/defines_preprocessed.asm new file mode 100755 index 0000000..c4c48e7 --- /dev/null +++ b/listings/chap5/defines_preprocessed/defines_preprocessed.asm @@ -0,0 +1,14 @@ +%line 2+1 defines.asm + +%line 6+1 defines.asm + + +mov rax, 1 * 3 +mov rax, 1 * 3 +mov rax, 3 + + + +mov rax, 100 * 3 +mov rax, 1 * 3 +mov rax, 3 diff --git a/listings/chap5/defining_in_cla/defining_in_cla.asm b/listings/chap5/defining_in_cla/defining_in_cla.asm new file mode 100755 index 0000000..7e3684e --- /dev/null +++ b/listings/chap5/defining_in_cla/defining_in_cla.asm @@ -0,0 +1,3 @@ +%ifdef flag +hellostring: db "Hello",0 +%endif diff --git a/listings/chap5/executable_object/a b/listings/chap5/executable_object/a new file mode 100755 index 0000000000000000000000000000000000000000..1ea87c3ecc44773bf4b7ca3834f2cfeebb8d465f GIT binary patch literal 1208 zcmbtTJ5R$f5WXbkDF)b(U?>w3LP3-TF(3v&9S|FH>Zq17G*pT$9uq4+r(?y+A7Dgc zgbfy?4otxLeAlK48;;`d?z@N2KKt(E>@*AlkP*TmIPDpZi1IVQS4b*z`w*gi4jSY; zGclob#G1!f)&v2X#JDwP@qZ)DVTUBaW#-obm!i?6xjht*_He{8B#~G9;e)yN??)eo z^Ai`iB}{B?bE{H_jV(N8B3XT7A?_-xAWn^uh(9sH-4Dk5ow!6;vQ#-?0V4dQX5rmA zG~n|`biq{;>UlPpmwk%A-&;L@iyVmObMz4h1OdEM>OV$a&fa_a`JDJ*d@sayL418( zMSNJ>Z^r%*bf)ToINrgor2U=|jFrj3b>d1DyCSpzyF!G=7PyY}RH}Pm`nkT&bfF@cBS_J;2H+Y9d>!-9t=3?9-~0@OkE#ce8diNU*tVh{Tq^qaT9SK ze~FiSHDdeH_}zG-8oyGCC+AL)+Re 65535 + %exitrep +%endif + dq b +%assign t a+b +%assign a b +%assign b t +%endrep + diff --git a/listings/chap5/hello_elfheader/hello_elfheader b/listings/chap5/hello_elfheader/hello_elfheader new file mode 100755 index 0000000..bb6ace7 --- /dev/null +++ b/listings/chap5/hello_elfheader/hello_elfheader @@ -0,0 +1,20 @@ +ELF Header: + Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 + Class: ELF64 + Data: 2's complement, little endian + Version: 1 (current) + OS/ABI: UNIX - System V + ABI Version: 0 + Type: EXEC (Executable file) + Machine: Advanced Micro Devices X86-64 + Version: 0x1 + Entry point address: 0x4000b0 + Start of program headers: 64 (bytes into file) + Start of section headers: 552 (bytes into file) + Flags: 0x0 + Size of this header: 64 (bytes) + Size of program headers: 56 (bytes) + Number of program headers: 2 + Size of section headers: 64 (bytes) + Number of section headers: 6 + Section header string table index: 3 diff --git a/listings/chap5/libso/Makefile b/listings/chap5/libso/Makefile new file mode 100755 index 0000000..c0501b5 --- /dev/null +++ b/listings/chap5/libso/Makefile @@ -0,0 +1,18 @@ +AFLAGS = -f elf64 +all: main + + +main.o: main.asm + nasm $(AFLAGS) -o main.o main.asm + +libso.o: libso.asm + nasm $(AFLAGS) -o libso.o libso.asm + +libso.so: libso.o + ld -shared -o libso.so libso.o --dynamic-linker=/lib64/ld-linux-x86-64.so.2 + +main: main.o libso.so + ld -o main main.o -d libso.so + +clean: + rm -f main.o libso.o libso.so main diff --git a/listings/chap5/libso/libso b/listings/chap5/libso/libso new file mode 100755 index 0000000..abf9229 --- /dev/null +++ b/listings/chap5/libso/libso @@ -0,0 +1,75 @@ +> nasm -f elf64 -o main.o main.asm +> nasm -f elf64 -o libso.o libso.asm +> ld -o main main.o -d libso.so +> ld -shared -o libso.so libso.o --dynamic-linker=/lib64/ld-linux-x86-64.so.2 +> readelf -S libso.so +There are 13 section headers, starting at offset 0x5a0: + +Section Headers: + [Nr] Name Type Address Offset + Size EntSize Flags Link Info Align + [ 0] NULL 0000000000000000 00000000 + 0000000000000000 0000000000000000 0 0 0 + [ 1] .hash HASH 00000000000000e8 000000e8 + 000000000000002c 0000000000000004 A 2 0 8 + [ 2] .dynsym DYNSYM 0000000000000118 00000118 + 0000000000000090 0000000000000018 A 3 2 8 + [ 3] .dynstr STRTAB 00000000000001a8 000001a8 + 000000000000001e 0000000000000000 A 0 0 1 + [ 4] .rela.dyn RELA 00000000000001c8 000001c8 + 0000000000000018 0000000000000018 A 2 0 8 + [ 5] .text PROGBITS 00000000000001e0 000001e0 + 000000000000001c 0000000000000000 AX 0 0 16 + [ 6] .rodata PROGBITS 00000000000001fc 000001fc + 000000000000001a 0000000000000000 A 0 0 4 + [ 7] .eh_frame PROGBITS 0000000000000218 00000218 + 0000000000000000 0000000000000000 A 0 0 8 + [ 8] .dynamic DYNAMIC 0000000000200218 00000218 + 00000000000000f0 0000000000000010 WA 3 0 8 + [ 9] .got.plt PROGBITS 0000000000200308 00000308 + 0000000000000018 0000000000000008 WA 0 0 8 + [10] .shstrtab STRTAB 0000000000000000 00000320 + 0000000000000065 0000000000000000 0 0 1 + [11] .symtab SYMTAB 0000000000000000 00000388 + 00000000000001c8 0000000000000018 12 15 8 + [12] .strtab STRTAB 0000000000000000 00000550 + 000000000000004f 0000000000000000 0 0 1 +Key to Flags: + W (write), A (alloc), X (execute), M (merge), S (strings), l (large) + I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown) + O (extra OS processing required) o (OS specific), p (processor specific) + +> readelf -S main +There are 14 section headers, starting at offset 0x650: + +Section Headers: + [Nr] Name Type Address Offset + Size EntSize Flags Link Info Align + [ 0] NULL 0000000000000000 00000000 + 0000000000000000 0000000000000000 0 0 0 + [ 1] .interp PROGBITS 0000000000400158 00000158 + 000000000000000f 0000000000000000 A 0 0 1 + [ 2] .hash HASH 0000000000400168 00000168 + 0000000000000028 0000000000000004 A 3 0 8 + [ 3] .dynsym DYNSYM 0000000000400190 00000190 + 0000000000000078 0000000000000018 A 4 1 8 + [ 4] .dynstr STRTAB 0000000000400208 00000208 + 0000000000000027 0000000000000000 A 0 0 1 + [ 5] .rela.plt RELA 0000000000400230 00000230 + 0000000000000018 0000000000000018 AI 3 6 8 + [ 6] .plt PROGBITS 0000000000400250 00000250 + 0000000000000020 0000000000000010 AX 0 0 16 + [ 7] .text PROGBITS 0000000000400270 00000270 + 0000000000000014 0000000000000000 AX 0 0 16 + [ 8] .eh_frame PROGBITS 0000000000400288 00000288 + 0000000000000000 0000000000000000 A 0 0 8 + [ 9] .dynamic DYNAMIC 0000000000600288 00000288 + 0000000000000110 0000000000000010 WA 4 0 8 + [10] .got.plt PROGBITS 0000000000600398 00000398 + 0000000000000020 0000000000000008 WA 0 0 8 + [11] .shstrtab STRTAB 0000000000000000 000003b8 + 0000000000000065 0000000000000000 0 0 1 + [12] .symtab SYMTAB 0000000000000000 00000420 + 00000000000001e0 0000000000000018 13 15 8 + [13] .strtab STRTAB 0000000000000000 00000600 + 000000000000004d 0000000000000000 0 0 1 diff --git a/listings/chap5/libso/libso.asm b/listings/chap5/libso/libso.asm new file mode 100755 index 0000000..3b338aa --- /dev/null +++ b/listings/chap5/libso/libso.asm @@ -0,0 +1,15 @@ +extern _GLOBAL_OFFSET_TABLE_ + +global func:function + +section .rodata +message: db "Shared object wrote this", 10, 0 + +section .text +func: + mov rax, 1 + mov rdi, 1 + mov rsi, message + mov rdx, 14 + syscall +ret diff --git a/listings/chap5/libso/main.asm b/listings/chap5/libso/main.asm new file mode 100755 index 0000000..10421a0 --- /dev/null +++ b/listings/chap5/libso/main.asm @@ -0,0 +1,12 @@ +global _start +extern func + +section .text +_start: + mov rdi, 10 + call func + mov rdi, rax + mov rax, 60 + syscall + + diff --git a/listings/chap5/libso_main/Makefile b/listings/chap5/libso_main/Makefile new file mode 100755 index 0000000..230d8c2 --- /dev/null +++ b/listings/chap5/libso_main/Makefile @@ -0,0 +1,18 @@ +AFLAGS = -f elf64 +all: main + + +main.o: main.asm + nasm $(AFLAGS) -o main.o main.asm + +libso.o: libso.asm + nasm $(AFLAGS) -o libso.o libso.asm + +libso.so: libso.o + ld -shared -o libso.so libso.o + +main: main.o libso.so + ld -o main main.o -d libso.so + +clean: + rm -f main.o libso.o libso.so main diff --git a/listings/chap5/libso_main/libso_main.asm b/listings/chap5/libso_main/libso_main.asm new file mode 100755 index 0000000..10421a0 --- /dev/null +++ b/listings/chap5/libso_main/libso_main.asm @@ -0,0 +1,12 @@ +global _start +extern func + +section .text +_start: + mov rdi, 10 + call func + mov rdi, rax + mov rax, 60 + syscall + + diff --git a/listings/chap5/linked_list_ex/linked_list_ex.asm b/listings/chap5/linked_list_ex/linked_list_ex.asm new file mode 100755 index 0000000..a8aba3c --- /dev/null +++ b/listings/chap5/linked_list_ex/linked_list_ex.asm @@ -0,0 +1,15 @@ +section .data + +x1: +dq x2 +dq 100 + +x2: +dq x3 +dq 200 + +x3: +dq 0 +dq 300 + + diff --git a/listings/chap5/linked_list_ex_macro/linked_list_ex_macro.asm b/listings/chap5/linked_list_ex_macro/linked_list_ex_macro.asm new file mode 100755 index 0000000..025fa02 --- /dev/null +++ b/listings/chap5/linked_list_ex_macro/linked_list_ex_macro.asm @@ -0,0 +1,12 @@ +section .data + +colon "third word", third_word +db "third word explanation", 0 + +colon "second word", second_word +db "second word explanation", 0 + +colon "first word", first_word +db "first word explanation", 0 + + diff --git a/listings/chap5/macro_arg_types/e b/listings/chap5/macro_arg_types/e new file mode 100755 index 0000000000000000000000000000000000000000..490185dc9f34ff37ae82086fd8502d0759233734 GIT binary patch literal 1112 zcmbu8ze^)Q6vtnpYcz<7g&45$u(Jr-$Q6gAQC@L{O|a5+HA^Do7ugX^WgrL!!6FBD ze}J8xjifTcfTE4y|8N*Ec-WlR?Y-H36XSSi+RauQ%b(91PmLS!Y_^L30{D+QS5xGy;0!pPZZ2=}jrfo|*JslD2{ zcU>227Y$k4l+${|XeY7u6RX`A*8X7a7rM8XA)xs@OmUpQ!{^^vy_q|hB!>H~oi4gp zol~z-cdebVv)MuzuzAn#*ZEGN<}B5Aj>&3#AuD1)+$raTwMi;UzGjpq>|H@g?~DQ3 zjY{wP{Y3fpgYe|)WfLBFn?J+6s`Xi5Ue`D>|EBRI^AnA4Fu&Azk-6F*&!uUXo+y2n zIuDBPF&_(TDCFtke|VjFRLh5)wN)yZRw-?Ya?y6;mXib8^6h-u%-Z?1$h`LA*+QYH zAv>RfB2@^}FJxzjNT2Cf=E~kt07|t=0!(w$ag=SREMb8u+kJRUQ3v_&hq#kE7Zvu8 zSd~PT!8%UbcjbCfb&o#vh;PWX`iJy`{ebN`PF!IfBrb2zFvnx8Bc%UYzrsy_aGnx< F{l7m|pV0sS literal 0 HcmV?d00001 diff --git a/listings/chap5/macro_arg_types/macro_arg_types.asm b/listings/chap5/macro_arg_types/macro_arg_types.asm new file mode 100755 index 0000000..70f380b --- /dev/null +++ b/listings/chap5/macro_arg_types/macro_arg_types.asm @@ -0,0 +1,23 @@ +%macro print 1 + %ifid %1 + mov rdi, %1 + call print_string + %else + + %ifnum %1 + mov rdi, %1 + call print_uint + %else + %error "String literals are not supported yet" + %endif + %endif + +%endmacro + +myhello: db 'hello', 10, 0 +_start: + print myhello + print 42 + mov rax, 60 + syscall + diff --git a/listings/chap5/macro_arg_types_preprocessed/macro_arg_types_preprocessed.asm b/listings/chap5/macro_arg_types_preprocessed/macro_arg_types_preprocessed.asm new file mode 100755 index 0000000..8a7c150 --- /dev/null +++ b/listings/chap5/macro_arg_types_preprocessed/macro_arg_types_preprocessed.asm @@ -0,0 +1,19 @@ + +%line 73+1 macro_arg_types/macro_arg_types.asm + +myhello: db 'hello', 10, 0 +_start: + mov rdi, myhello +%line 76+0 macro_arg_types/macro_arg_types.asm + call print_string + +%line 77+1 macro_arg_types/macro_arg_types.asm + +%line 77+0 macro_arg_types/macro_arg_types.asm + mov rdi, 42 + call print_uint + +%line 78+1 macro_arg_types/macro_arg_types.asm + mov rax, 60 + syscall + diff --git a/listings/chap5/macro_asm_parts/macro_asm_parts.asm b/listings/chap5/macro_asm_parts/macro_asm_parts.asm new file mode 100755 index 0000000..2d3078c --- /dev/null +++ b/listings/chap5/macro_asm_parts/macro_asm_parts.asm @@ -0,0 +1,4 @@ +%define a mov rax, + %define b rbx + + a b diff --git a/listings/chap5/macro_local_labels/macro_local_labels.asm b/listings/chap5/macro_local_labels/macro_local_labels.asm new file mode 100755 index 0000000..1e26c15 --- /dev/null +++ b/listings/chap5/macro_local_labels/macro_local_labels.asm @@ -0,0 +1,10 @@ +%macro mymacro 0 +%%labelname: +%%labelname: +%endmacro + +mymacro + +mymacro + +mymacro diff --git a/listings/chap5/macro_local_labels_inst/macro_local_labels_inst.asm b/listings/chap5/macro_local_labels_inst/macro_local_labels_inst.asm new file mode 100755 index 0000000..7896ec2 --- /dev/null +++ b/listings/chap5/macro_local_labels_inst/macro_local_labels_inst.asm @@ -0,0 +1,15 @@ +%line 5+1 macro_local_labels/macro_local_labels.asm + +..@0.labelname: +%line 6+0 macro_local_labels/macro_local_labels.asm +..@0.labelname: +%line 7+1 macro_local_labels/macro_local_labels.asm + +..@1.labelname: +%line 8+0 macro_local_labels/macro_local_labels.asm +..@1.labelname: +%line 9+1 macro_local_labels/macro_local_labels.asm + +..@2.labelname: +%line 10+0 macro_local_labels/macro_local_labels.asm +..@2.labelname: diff --git a/listings/chap5/macro_simple_3arg/macro_simple_3arg.asm b/listings/chap5/macro_simple_3arg/macro_simple_3arg.asm new file mode 100755 index 0000000..755d285 --- /dev/null +++ b/listings/chap5/macro_simple_3arg/macro_simple_3arg.asm @@ -0,0 +1,5 @@ +%macro test 3 +dq %1 +dq %2 +dq %3 +%endmacro diff --git a/listings/chap5/macro_simple_3arg_inst/macro_simple_3arg_inst.asm b/listings/chap5/macro_simple_3arg_inst/macro_simple_3arg_inst.asm new file mode 100755 index 0000000..0f69573 --- /dev/null +++ b/listings/chap5/macro_simple_3arg_inst/macro_simple_3arg_inst.asm @@ -0,0 +1,3 @@ +dq 666 +dq 555 +dq 444 diff --git a/listings/chap5/macroif/macroif.asm b/listings/chap5/macroif/macroif.asm new file mode 100755 index 0000000..2497404 --- /dev/null +++ b/listings/chap5/macroif/macroif.asm @@ -0,0 +1,16 @@ +BITS 64 +%define x 5 + +%if x == 10 + +mov rax, 100 + +%elif x == 15 + +mov rax, 115 + +%elif x == 200 +mov rax, 0 +%else +mov rax, rbx +%endif diff --git a/listings/chap5/macroif_preprocessed/macroif_preprocessed.asm b/listings/chap5/macroif_preprocessed/macroif_preprocessed.asm new file mode 100755 index 0000000..23d58df --- /dev/null +++ b/listings/chap5/macroif_preprocessed/macroif_preprocessed.asm @@ -0,0 +1,6 @@ +%line 1+1 if.asm +[bits 64] + + +%line 15+1 if.asm +mov rax, rbx diff --git a/listings/chap5/nm/nm b/listings/chap5/nm/nm new file mode 100755 index 0000000..b024cce --- /dev/null +++ b/listings/chap5/nm/nm @@ -0,0 +1,6 @@ +> nm main.o +0000000000000000 b bssvar +0000000000000000 d datavar + U somewhere +000000000000000a T _start +000000000000000b t textlabel diff --git a/listings/chap5/objdump_d/objdump_d b/listings/chap5/objdump_d/objdump_d new file mode 100755 index 0000000..0cabff3 --- /dev/null +++ b/listings/chap5/objdump_d/objdump_d @@ -0,0 +1,21 @@ +> objdump -D -M intel-mnemonic main.o +main.o: file format elf64-x86-64 +Disassembly of section .data: +0000000000000000 : ... +0000000000000008 : ... +Disassembly of section .bss: +0000000000000000 : ... +0000000002000000 : ... +Disassembly of section .text: +0000000000000000 <_start-0x28>: + 0: 48 b8 00 00 00 00 00 movabs rax,0x0 + 7: 00 00 00 + a: 48 b8 00 00 00 00 00 movabs rax,0x0 + 11: 00 00 00 + 14: 48 b8 00 00 00 00 00 movabs rax,0x0 + 1b: 00 00 00 + 1e: 48 ba 00 00 00 00 00 movabs rdx,0x0 + 25: 00 00 00 +0000000000000028 <_start>: + 28: c3 ret +0000000000000029 : diff --git a/listings/chap5/objdump_tf/objdump_tf b/listings/chap5/objdump_tf/objdump_tf new file mode 100755 index 0000000..8b92a2a --- /dev/null +++ b/listings/chap5/objdump_tf/objdump_tf @@ -0,0 +1,21 @@ +> nasm -f elf64 symbols.asm +> nasm -f elf64 executable_object.asm +> ld symbols.o executable_object.o -o main +> objdump -tf main + +main: file format elf64-x86-64 +architecture: i386:x86-64, flags 0x00000112: +EXEC_P, HAS_SYMS, D_PAGED +start address 0x0000000000000000 + +SYMBOL TABLE: +00000000004000b0 l d .code 0000000000000000 .code +00000000006000bc l d .data 0000000000000000 .data +0000000000000000 l df *ABS* 0000000000000000 executable_object.asm +00000000006000c4 l .data 0000000000000000 private +00000000006000bc g .data 0000000000000000 somewhere +0000000000000000 *UND* 0000000000000000 _start +00000000006000cc g .data 0000000000000000 __bss_start +00000000004000b0 g F .code 0000000000000000 func +00000000006000cc g .data 0000000000000000 _edata +00000000006000d0 g .data 0000000000000000 _end diff --git a/listings/chap5/prime/prime.asm b/listings/chap5/prime/prime.asm new file mode 100755 index 0000000..6a2c1f0 --- /dev/null +++ b/listings/chap5/prime/prime.asm @@ -0,0 +1,16 @@ +%assign limit 15 +is_prime: db 0, 0, 1 +%assign n 3 +%rep limit + %assign current 1 + %assign i 1 + %rep n/2 + %assign i i+1 + %if n % i = 0 + %assign current 0 + %exitrep + %endif + %endrep +db current ; n + %assign n n+1 +%endrep diff --git a/listings/chap5/prime_preprocessed/prime_preprocessed.asm b/listings/chap5/prime_preprocessed/prime_preprocessed.asm new file mode 100755 index 0000000..4a30081 --- /dev/null +++ b/listings/chap5/prime_preprocessed/prime_preprocessed.asm @@ -0,0 +1,19 @@ +%line 2+1 prime/prime.asm +is_prime: db 0, 0, 1 +%line 16+1 prime/prime.asm +db 1 +%line 16+0 prime/prime.asm +db 0 +db 1 +db 0 +db 1 +db 0 +db 0 +db 0 +db 1 +db 0 +db 1 +db 0 +db 0 +db 0 +db 1 diff --git a/listings/chap5/pushr/pushr.asm b/listings/chap5/pushr/pushr.asm new file mode 100755 index 0000000..771a345 --- /dev/null +++ b/listings/chap5/pushr/pushr.asm @@ -0,0 +1,10 @@ +%macro pushr 1 +%ifidn %1, rflags +pushf +%else +push %1 +%endif +%endmacro + +pushr rax +pushr rflags diff --git a/listings/chap5/pushr_preprocessed/pushr_preprocessed.asm b/listings/chap5/pushr_preprocessed/pushr_preprocessed.asm new file mode 100755 index 0000000..76748d3 --- /dev/null +++ b/listings/chap5/pushr_preprocessed/pushr_preprocessed.asm @@ -0,0 +1,4 @@ +%line 8+1 pushr/pushr.asm + +push rax +pushf diff --git a/listings/chap5/readelf_relocs/readelf_relocs b/listings/chap5/readelf_relocs/readelf_relocs new file mode 100755 index 0000000..9f95834 --- /dev/null +++ b/listings/chap5/readelf_relocs/readelf_relocs @@ -0,0 +1,7 @@ +> readelf --relocs main.o +Relocation section '.rela.text' at offset 0x440 contains 4 entries: + Offset Info Type Sym. Value Name+Addend +000000000002 000200000001 R_X86_64_64 0000000000000000 .data + 0 +00000000000c 000300000001 R_X86_64_64 0000000000000000 .bss + 0 +000000000016 000300000001 R_X86_64_64 0000000000000000 .bss + 2000000 +000000000020 000200000001 R_X86_64_64 0000000000000000 .data + 8 diff --git a/listings/chap5/rep/rep.asm b/listings/chap5/rep/rep.asm new file mode 100755 index 0000000..ab91254 --- /dev/null +++ b/listings/chap5/rep/rep.asm @@ -0,0 +1,8 @@ +%assign x 1 +%assign a 0 +%rep 10 +%assign a x + a +%assign x x + 1 +%endrep + +result: dq a diff --git a/listings/chap5/rep_preprocessed/rep_preprocessed.asm b/listings/chap5/rep_preprocessed/rep_preprocessed.asm new file mode 100755 index 0000000..66ddc50 --- /dev/null +++ b/listings/chap5/rep_preprocessed/rep_preprocessed.asm @@ -0,0 +1,3 @@ +%line 7+1 rep/rep.asm + +result: dq 55 diff --git a/listings/chap5/symbols/symbols b/listings/chap5/symbols/symbols new file mode 100755 index 0000000..c153432 --- /dev/null +++ b/listings/chap5/symbols/symbols @@ -0,0 +1,18 @@ +> nasm -f elf64 main.asm && objdump -tf -m intel main.o +main.o: file format elf64-x86-64 +architecture: i386:x86-64, flags 0x00000011: +HAS_RELOC, HAS_SYMS +start address 0x0000000000000000 +SYMBOL TABLE: +0000000000000000 l df *ABS* 0000000000000000 main.asm +0000000000000000 l d .data 0000000000000000 .data +0000000000000000 l d .bss 0000000000000000 .bss +0000000000000000 l d .text 0000000000000000 .text +0000000000000000 l .data 0000000000000000 datavar1 +0000000000000008 l .data 0000000000000000 datavar2 +0000000000000000 l .bss 0000000000000000 bssvar1 +0000000002000000 l .bss 0000000000000000 bssvar2 +0000000000000029 l .text 0000000000000000 textlabel +0000000000000000 *UND* 0000000000000000 somewhere +0000000000000028 g .text 0000000000000000 _start + diff --git a/listings/chap5/symbols/symbols.asm b/listings/chap5/symbols/symbols.asm new file mode 100755 index 0000000..1cf60c2 --- /dev/null +++ b/listings/chap5/symbols/symbols.asm @@ -0,0 +1,20 @@ +section .data +datavar1: dq 1488 +datavar2: dq 42 + +section .bss +bssvar1: resq 4*1024*1024 +bssvar2: resq 1 + +section .text + +extern somewhere +global _start + mov rax, datavar1 + mov rax, bssvar1 + mov rax, bssvar2 + mov rdx, datavar2 +_start: +jmp _start + ret +textlabel: dq 0 diff --git a/listings/chap5/symbols_maps/symbols_maps b/listings/chap5/symbols_maps/symbols_maps new file mode 100755 index 0000000..7b1295f --- /dev/null +++ b/listings/chap5/symbols_maps/symbols_maps @@ -0,0 +1,16 @@ +00400000-00401000 r-xp 00000000 08:01 1176842 + /home/sayon/repos/spbook/en/listings/chap5/main + +00600000-00601000 rwxp 00000000 08:01 1176842 + /home/sayon/repos/spbook/en/listings/chap5/main + +00601000-02601000 rwxp 00000000 00:00 0 + +7ffe19cf2000-7ffe19d13000 rwxp 00000000 00:00 0 + [stack] +7ffe19d3e000-7ffe19d40000 r-xp 00000000 00:00 0 + [vdso] +7ffe19d40000-7ffe19d42000 r--p 00000000 00:00 0 + [vvar] +ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 + [vsyscall] diff --git a/listings/chap5/symbols_pht/symbols_pht b/listings/chap5/symbols_pht/symbols_pht new file mode 100755 index 0000000..2ae54f6 --- /dev/null +++ b/listings/chap5/symbols_pht/symbols_pht @@ -0,0 +1,20 @@ +> nasm -f elf64 symbols.asm +> nasm -f elf64 executable_object.asm +> ld symbols.o executable_object.o -o main +> readelf -l main +Elf file type is EXEC (Executable file) +Entry point 0x4000d8 +There are 2 program headers, starting at offset 64 + +Program Headers: + Type Offset VirtAddr PhysAddr + FileSiz MemSiz Flags Align + LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000 + 0x00000000000000e3 0x00000000000000e3 R E 200000 + LOAD 0x00000000000000e4 0x00000000006000e4 0x00000000006000e4 + 0x0000000000000010 0x000000000200001c RW 200000 + + Section to Segment mapping: + Segment Sections... + 00 .text + 01 .data .bss diff --git a/listings/chap7/automaton_example_bits/automaton_example_bits.asm b/listings/chap7/automaton_example_bits/automaton_example_bits.asm new file mode 100755 index 0000000..9f4f3bb --- /dev/null +++ b/listings/chap7/automaton_example_bits/automaton_example_bits.asm @@ -0,0 +1,43 @@ +section .text +; getsymbol is a routine to +; read a symbol (f.e. from stdin) +; into al +_A: + call getsymbol + cmp al, '+' + je _B + cmp al, '-' + je _B +; The indices of the digit characters in ASCII +; tables fill a range from '0' = 0x30 to '9' = 0x39 +; This logic implements the transitions to labels +; _E and _C + cmp al, '0' + jb _E + cmp al, '9' + ja _E + jmp _C + +_B: + call getsymbol + cmp al, '0' + jb _E + cmp al, '9' + ja _E + jmp _C + +_C: + call getsymbol + cmp al, '0' + jb _E + cmp al, '9' + ja _E + test al, al + jz _D + jmp _C + +_D: +; code to notify about success + +_E: +; code to notify about failure diff --git a/listings/chap7/forth_colon_usage/forth_colon_usage.asm b/listings/chap7/forth_colon_usage/forth_colon_usage.asm new file mode 100755 index 0000000..645ef02 --- /dev/null +++ b/listings/chap7/forth_colon_usage/forth_colon_usage.asm @@ -0,0 +1,4 @@ +colon '>', greater + dq xt_swap + dq xt_less + dq exit diff --git a/listings/chap7/forth_dict_example_macro/forth_dict_example_macro.asm b/listings/chap7/forth_dict_example_macro/forth_dict_example_macro.asm new file mode 100755 index 0000000..ecc5a7f --- /dev/null +++ b/listings/chap7/forth_dict_example_macro/forth_dict_example_macro.asm @@ -0,0 +1,4 @@ +native '+', plus + pop rax + add [rsp], rax + jmp next diff --git a/listings/chap7/forth_dict_example_nomacro/forth_dict_example_nomacro.asm b/listings/chap7/forth_dict_example_nomacro/forth_dict_example_nomacro.asm new file mode 100755 index 0000000..27a471d --- /dev/null +++ b/listings/chap7/forth_dict_example_nomacro/forth_dict_example_nomacro.asm @@ -0,0 +1,12 @@ +section .data +w_plus: + dq w_mul ; previous + db '+',0 + db 0 +xt_plus: + dq plus_impl +section .text + plus_impl: + pop rax + add [rsp], rax + jmp next diff --git a/listings/chap7/forth_dict_sample/forth_dict_sample.asm b/listings/chap7/forth_dict_sample/forth_dict_sample.asm new file mode 100755 index 0000000..442d26d --- /dev/null +++ b/listings/chap7/forth_dict_sample/forth_dict_sample.asm @@ -0,0 +1,33 @@ +section .data +w_plus: + dq 0 ; The first word's pointer to the previous word is zero + db '+',0 + db 0 ; No flags +xt_plus: ; Execution token for `plus`, equal to + ; the address of its implementation + dq plus_impl +w_dup: + dq w_plus + db 'dup', 0 + db 0 +xt_dup: + dq dup_impl +w_double: + dq w_dup + db 'double', 0 + db 0 + dq docol ; The `docol` address -- one level of indirection + dq xt_dup ; The words consisting `dup` start here. + dq xt_plus + dq xt_exit + +last_word: dq w_double +section .text + plus_impl: + pop rax + add rax, [rsp] + mov [rsp], rax + jmp next + dup_impl: + push qword [rsp] + jmp next diff --git a/listings/chap7/forth_discr/forth_discr b/listings/chap7/forth_discr/forth_discr new file mode 100755 index 0000000..714c937 --- /dev/null +++ b/listings/chap7/forth_discr/forth_discr @@ -0,0 +1,3 @@ +: sq dup * ; +: discr rot 4 * * swap sq swap - ; +1 2 3 discr diff --git a/listings/chap7/forth_docol/forth_docol.asm b/listings/chap7/forth_docol/forth_docol.asm new file mode 100755 index 0000000..1202188 --- /dev/null +++ b/listings/chap7/forth_docol/forth_docol.asm @@ -0,0 +1,11 @@ +docol: + sub rstack, 8 + mov [rstack], pc + add w, 8 ; предполагая размер ячейки 8 байт + mov pc, w + jmp next + +exit: + mov pc, [rstack] + add rstack, 8 + jmp next \ No newline at end of file diff --git a/listings/chap7/forth_interpreter_end/forth_interpreter_end.asm b/listings/chap7/forth_interpreter_end/forth_interpreter_end.asm new file mode 100755 index 0000000..2218426 --- /dev/null +++ b/listings/chap7/forth_interpreter_end/forth_interpreter_end.asm @@ -0,0 +1,2 @@ +mov pc, xt_interpreter +jmp next diff --git a/listings/chap7/forth_next/forth_next.asm b/listings/chap7/forth_next/forth_next.asm new file mode 100755 index 0000000..019943e --- /dev/null +++ b/listings/chap7/forth_next/forth_next.asm @@ -0,0 +1,5 @@ +next: + mov w, pc + add pc, 8 ; the cell size is 8 bytes + mov w, [w] + jmp [w] diff --git a/listings/chap7/forth_program_stub/forth_program_stub.asm b/listings/chap7/forth_program_stub/forth_program_stub.asm new file mode 100755 index 0000000..4a5f361 --- /dev/null +++ b/listings/chap7/forth_program_stub/forth_program_stub.asm @@ -0,0 +1,3 @@ +program_stub: dq 0 +xt_interpreter: dq .interpreter +.interpreter: dq interpreter_loop diff --git a/listings/chap7/forth_sq/forth_sq b/listings/chap7/forth_sq/forth_sq new file mode 100755 index 0000000..d6bb4d1 --- /dev/null +++ b/listings/chap7/forth_sq/forth_sq @@ -0,0 +1 @@ +: sq dup * ; diff --git a/listings/chap7/itc/itc.asm b/listings/chap7/itc/itc.asm new file mode 100755 index 0000000..cfba221 --- /dev/null +++ b/listings/chap7/itc/itc.asm @@ -0,0 +1,112 @@ +%include "lib.inc" + +global _start + +%define pc r15 +%define w r14 +%define rstack r13 + +section .bss +resq 1023 +rstack_start: resq 1 +input_buf: resb 1024 + + +section .text + +; this one cell is the program +main_stub: dq xt_main + +; The dictionary starts here +; The first word is shown in full +; Then we omit flags and links between nodes for brevity +; Each word stores an address of its assembly implementation + +; Drops the topmost element from the stack +dq 0 ; There is no previous node +db "drop", 0 +db 0 ; Flags = 0 +xt_drop: dq i_drop +i_drop: + add rsp, 8 + jmp next + +; Initializes registers +xt_init: dq i_init +i_init: + mov rstack, rstack_start + mov pc, main_stub + jmp next + +; Saves PC when the colon word starts +xt_docol: dq i_docol +i_docol: + sub rstack, 8 + mov [rstack], pc + add w, 8 + mov pc, w + jmp next + +; Returns from the colon word +xt_exit: dq i_exit +i_exit: + mov pc, [rstack] + add rstack, 8 + jmp next + +; Takes a buffer pointer from stack +; Reads a word from input and stores it +; starting in the given buffer +xt_word: dq i_word +i_word: + pop rdi + call read_word + push rdx + jmp next + +; Takes a pointer to a string from the stack +; and prints it +xt_prints: dq i_prints +i_prints: + pop rdi + call print_string + jmp next + +; Exits program +xt_bye: dq i_bye +i_bye: + mov rax, 60 + xor rdi, rdi + syscall + +; Loads the predefined buffer address +xt_inbuf: dq i_inbuf +i_inbuf: + push qword input_buf + jmp next + +; This is a colon word, it stores +; execution tokens. Each token +; corresponds to a Forth word to be +; executed +xt_main: dq i_docol + dq xt_inbuf + dq xt_word + dq xt_drop + dq xt_inbuf + dq xt_prints + dq xt_bye + +; The inner interpreter. These three lines +; fetch the next instruction and start its +; execution +next: + mov w, [pc] + add pc, 8 + jmp [w] + +; The program starts execution from the init word +_start: jmp i_init + + + diff --git a/listings/chap7/native_overloading/native_overloading.asm b/listings/chap7/native_overloading/native_overloading.asm new file mode 100755 index 0000000..fd1c5a3 --- /dev/null +++ b/listings/chap7/native_overloading/native_overloading.asm @@ -0,0 +1,3 @@ +%macro native 2 +native %1, %2, 0 +%endmacro diff --git a/listings/chap8/assignment_assoc/assignment_assoc.c b/listings/chap8/assignment_assoc/assignment_assoc.c new file mode 100755 index 0000000..9b12b97 --- /dev/null +++ b/listings/chap8/assignment_assoc/assignment_assoc.c @@ -0,0 +1,2 @@ +x = y = z; +(x = (y = z)); diff --git a/listings/chap8/block_example/block_example.c b/listings/chap8/block_example/block_example.c new file mode 100755 index 0000000..1297d1a --- /dev/null +++ b/listings/chap8/block_example/block_example.c @@ -0,0 +1,6 @@ +int y = 1 + 3; +{ + int x; + x = square( 2 ) + y; + printf( "%d\n", x ); +} diff --git a/listings/chap8/block_variables/block_variables.c b/listings/chap8/block_variables/block_variables.c new file mode 100755 index 0000000..1407746 --- /dev/null +++ b/listings/chap8/block_variables/block_variables.c @@ -0,0 +1,33 @@ +/* Good */ +void f(void) { + int x; + ... +} + +/* Bad: `x` is declared after `printf` call */ + +void f(void) { + int y = 12; + printf( "%d", y); + int x = 10; + ... +} + +/* Bad: `i` can not be declared in `for` initializer */ +for( int i = 0; i < 10; i++ ) { + ... +} + +/* Good: `i` is declared before `for` */ +int f(void) { + int i; + for( i = 0; i < 10; i++ ) { + ... + } +} + +/* Good: any block can have additional variables declared in its beginning */ +/* `x` is local to one `for` iteration and is always reinitialized to 10 */ +for( i = 0; i < 10; i++ ) { + int x = 10; +} diff --git a/listings/chap8/case_example/case_example.c b/listings/chap8/case_example/case_example.c new file mode 100755 index 0000000..38286f6 --- /dev/null +++ b/listings/chap8/case_example/case_example.c @@ -0,0 +1,14 @@ +int i = 10; +switch ( i ) { + case 1: /* if i is equal to 1...*/ + puts( "It is one" ); + break; /* Break is mandatory */ + + case 2: /* if i is equal to 2...*/ + puts( "It is two" ); + break; + + default: /* otherwise... */ + puts( "It is not one nor two" ); + break; +} diff --git a/listings/chap8/case_magic/case_magic.c b/listings/chap8/case_magic/case_magic.c new file mode 100755 index 0000000..1450006 --- /dev/null +++ b/listings/chap8/case_magic/case_magic.c @@ -0,0 +1,10 @@ +switch ( x ) { + case 0: + case 1: + case 10: + puts( "First case: x = 0, 1 or 10" ); + /* Notice the absence of `break`! */ + case 15: + puts( "Second case: x = 0, 1, 10 or 15" ); + break; +} diff --git a/listings/chap8/dangling_else/dangling_else.c b/listings/chap8/dangling_else/dangling_else.c new file mode 100755 index 0000000..5344c5c --- /dev/null +++ b/listings/chap8/dangling_else/dangling_else.c @@ -0,0 +1,13 @@ +if (x == 0) if (y == 0) { puts("A"); } else { puts("B"); } + +/* You might have considered one of the following interpretations. + * The compiler can issue a warning to prevent you */ + +if (x == 0) { + if (y == 0) { printf("A"); } + else { puts("B"); } +} + +if (x == 0) { + if (y == 0) { puts("A"); } +} else { puts("B"); } diff --git a/listings/chap8/define_example1/define_example1.c b/listings/chap8/define_example1/define_example1.c new file mode 100755 index 0000000..ad3e6bc --- /dev/null +++ b/listings/chap8/define_example1/define_example1.c @@ -0,0 +1 @@ +#define MY_CONST_VALUE 42 diff --git a/listings/chap8/define_example2/define_example2.c b/listings/chap8/define_example2/define_example2.c new file mode 100755 index 0000000..573dbf6 --- /dev/null +++ b/listings/chap8/define_example2/define_example2.c @@ -0,0 +1 @@ +#define MACRO_SQUARE( x ) ((x) * (x)) diff --git a/listings/chap8/define_parentheses/define_parentheses.c b/listings/chap8/define_parentheses/define_parentheses.c new file mode 100755 index 0000000..803f227 --- /dev/null +++ b/listings/chap8/define_parentheses/define_parentheses.c @@ -0,0 +1,3 @@ +#define SQUARE( x ) (x * x) + +int x = SQUARE( 4+1 ) diff --git a/listings/chap8/define_parentheses_preprocessed/define_parentheses_preprocessed.c b/listings/chap8/define_parentheses_preprocessed/define_parentheses_preprocessed.c new file mode 100755 index 0000000..94dcd79 --- /dev/null +++ b/listings/chap8/define_parentheses_preprocessed/define_parentheses_preprocessed.c @@ -0,0 +1 @@ +int x = 4+1 * 4+1 diff --git a/listings/chap8/div_assoc/div_assoc.c b/listings/chap8/div_assoc/div_assoc.c new file mode 100755 index 0000000..c857a5c --- /dev/null +++ b/listings/chap8/div_assoc/div_assoc.c @@ -0,0 +1,2 @@ + 40 / 2 / 4 +((40 / 2) / 4) diff --git a/listings/chap8/divisor/divisor.c b/listings/chap8/divisor/divisor.c new file mode 100755 index 0000000..6f04e8c --- /dev/null +++ b/listings/chap8/divisor/divisor.c @@ -0,0 +1,17 @@ +#include + +int first_divisor( int n ) { + int i; + if ( n == 1 ) return 1; + for( i = 2; i <= n; i++ ) + if ( n % i == 0 ) return i; + return 0; +} + +int main(void) { + int i; + for( i = 1; i < 11; i++ ) + printf( "%d \n", first_divisor( i ) ); + + return 0; +} diff --git a/listings/chap8/do_while_example/do_while_example.c b/listings/chap8/do_while_example/do_while_example.c new file mode 100755 index 0000000..632891f --- /dev/null +++ b/listings/chap8/do_while_example/do_while_example.c @@ -0,0 +1,6 @@ +int x = 10; +do { + printf("Hello\n"); + x = x - 1; +} +while ( x != 0 ); diff --git a/listings/chap8/expr_example/expr_example.c b/listings/chap8/expr_example/expr_example.c new file mode 100755 index 0000000..b461811 --- /dev/null +++ b/listings/chap8/expr_example/expr_example.c @@ -0,0 +1,4 @@ +1 +13 + 37 +17 + 89 * square( 1 ) +x diff --git a/listings/chap8/float_reinterpret/float_reinterpret.c b/listings/chap8/float_reinterpret/float_reinterpret.c new file mode 100755 index 0000000..ac8f690 --- /dev/null +++ b/listings/chap8/float_reinterpret/float_reinterpret.c @@ -0,0 +1,6 @@ +#include + +int main(void) { + printf("42.0 as an integer %d \n", 42.0); + return 0; +} diff --git a/listings/chap8/for_example/for_example.c b/listings/chap8/for_example/for_example.c new file mode 100755 index 0000000..2cca38e --- /dev/null +++ b/listings/chap8/for_example/for_example.c @@ -0,0 +1,5 @@ +int a[] = {1, 2, 3, 4}; /* an array of 4 elements */ +int i = 0; +for ( i = 0; i < 4; i++ ) { + printf( "%d", a[i]) +} diff --git a/listings/chap8/function_example/function_example.c b/listings/chap8/function_example/function_example.c new file mode 100755 index 0000000..fe05839 --- /dev/null +++ b/listings/chap8/function_example/function_example.c @@ -0,0 +1,8 @@ +int myfunc ( int a, int b ) +{ + return a + b; +} + +int other( int x ) { + return 1 + myfunc( 4, 5 ); +} diff --git a/listings/chap8/goto/goto.c b/listings/chap8/goto/goto.c new file mode 100755 index 0000000..d56b5c4 --- /dev/null +++ b/listings/chap8/goto/goto.c @@ -0,0 +1,10 @@ +int i; +int j; +for (i = 0; i < 100; i++ ) +for( j = 0; j < 100; j++ ) { + if (i * j == 432) + goto end; + else + printf("%d * %d != 432\n", i, j ); +} +end: diff --git a/listings/chap8/hello/hello.c b/listings/chap8/hello/hello.c new file mode 100755 index 0000000..799e56e --- /dev/null +++ b/listings/chap8/hello/hello.c @@ -0,0 +1,21 @@ +/* This is a comment. The next line has a preprocessor directive */ +#include + +/* `main` is the entry point for the program, like _start in assembly + * Actually, the hidden function _start is calling `main`. + * `main` returns the `return code` which is then given to the `exit` system + * call. + * The `void` keyword instead of argument list means that `main` accepts no + * arguments */ +int main(void) { + /* A variable local to `main`. Will be destructed as soon as `main` ends*/ + int x = 43; + int y; + y = x - 1; + /* Calling a standard function `printf` with three arguments. + * It will print 'Hello, world! y=42 x=43 + * All %d will be replaced by the consecutive arguments */ + printf( "Hello, world! y=%d x=%d\n", y, x); + + return 0; +} diff --git a/listings/chap8/if_example/if_example.c b/listings/chap8/if_example/if_example.c new file mode 100755 index 0000000..0b7ba00 --- /dev/null +++ b/listings/chap8/if_example/if_example.c @@ -0,0 +1,12 @@ +int x = 100; +if (42) { + puts("42 is not equal to zero and thus considered truth"); +} + +if (x > 3) { + puts("X is greater than 3"); +} +else +{ + puts("X is less than 3"); +} diff --git a/listings/chap8/if_no_braces/if_no_braces.c b/listings/chap8/if_no_braces/if_no_braces.c new file mode 100755 index 0000000..2b64d70 --- /dev/null +++ b/listings/chap8/if_no_braces/if_no_braces.c @@ -0,0 +1,4 @@ +if (x == 0) + puts("X is zero"); +else + puts("X is not zero"); diff --git a/listings/chap8/infinite_for/infinite_for.c b/listings/chap8/infinite_for/infinite_for.c new file mode 100755 index 0000000..6ab33a7 --- /dev/null +++ b/listings/chap8/infinite_for/infinite_for.c @@ -0,0 +1,4 @@ +for( ; ; ) { + /* this cycle will loop forever, unless `break` is issued in its body */ + break; /* `break` is here, so we stop iterating */ +} diff --git a/listings/chap8/is_fib/is_fib.c b/listings/chap8/is_fib/is_fib.c new file mode 100755 index 0000000..1b80bd3 --- /dev/null +++ b/listings/chap8/is_fib/is_fib.c @@ -0,0 +1,28 @@ +#include + +int is_fib( int n ) { + + int a = 1; + int b = 1; + if ( n == 1 ) return 1; + + while ( a <= n && b <= n ) { + int t = b; + + if (n == a || n == b) return 1; + b = a; + a = t + a; + } + return 0; + +} + +void check(int n) { printf( "%d -> %d\n", n, is_fib( n ) ); } + +int main(void) { + int i; + for( i = 1; i < 11; i = i + 1 ) { + check( i ); + } + return 0; +} diff --git a/listings/chap8/list_sum_bad/list_sum_bad.c b/listings/chap8/list_sum_bad/list_sum_bad.c new file mode 100755 index 0000000..f5aa9d8 --- /dev/null +++ b/listings/chap8/list_sum_bad/list_sum_bad.c @@ -0,0 +1,9 @@ +int list_sum( const struct list* l ) { + size_t i; + int sum = 0; + /* We do not want to launch the full size computation at each cycle iteration */ + size_t sz = list_size( l ) ; + for( i = 0; i < list_size(l); l = l-> next ) + sum = sum + l->value; + return sum; +} diff --git a/listings/chap8/logic_lazy/logic_lazy.c b/listings/chap8/logic_lazy/logic_lazy.c new file mode 100755 index 0000000..a10c864 --- /dev/null +++ b/listings/chap8/logic_lazy/logic_lazy.c @@ -0,0 +1,9 @@ +#include + +int f(void) { puts( "F" ); return 0; } +int g(void) { puts( "G" ); return 1; } + +int main(void) { + f() && g(); + return 0; +} diff --git a/listings/chap8/loop_cont/loop_cont.c b/listings/chap8/loop_cont/loop_cont.c new file mode 100755 index 0000000..6fb58e1 --- /dev/null +++ b/listings/chap8/loop_cont/loop_cont.c @@ -0,0 +1,5 @@ +int n = 0; +for( n = 0; n < 20; n++ ) { + if (n % 2) continue; + printf("%d is odd", n ); +} diff --git a/listings/chap8/no_arguments_ex/no_arguments_ex.c b/listings/chap8/no_arguments_ex/no_arguments_ex.c new file mode 100755 index 0000000..cdd1ea0 --- /dev/null +++ b/listings/chap8/no_arguments_ex/no_arguments_ex.c @@ -0,0 +1 @@ +int always_return_0( void ) { return 0; } diff --git a/listings/chap8/proc_example/proc_example.c b/listings/chap8/proc_example/proc_example.c new file mode 100755 index 0000000..2b79eb1 --- /dev/null +++ b/listings/chap8/proc_example/proc_example.c @@ -0,0 +1,4 @@ +void myproc ( int a, int b ) +{ + printf("%d", a+b); +} diff --git a/listings/chap8/rvalue_example/rvalue_example.c b/listings/chap8/rvalue_example/rvalue_example.c new file mode 100755 index 0000000..036c5c5 --- /dev/null +++ b/listings/chap8/rvalue_example/rvalue_example.c @@ -0,0 +1,3 @@ +4 = 2; +"abc"="bcd"; +square(3) = 9; diff --git a/listings/chap8/spacing_1/spacing_1.c b/listings/chap8/spacing_1/spacing_1.c new file mode 100755 index 0000000..8b7d3c5 --- /dev/null +++ b/listings/chap8/spacing_1/spacing_1.c @@ -0,0 +1,5 @@ + +int main (int argc , char * * argv) +{ + return 0; +} diff --git a/listings/chap8/spacing_2/spacing_2.c b/listings/chap8/spacing_2/spacing_2.c new file mode 100755 index 0000000..22ca09c --- /dev/null +++ b/listings/chap8/spacing_2/spacing_2.c @@ -0,0 +1,5 @@ + +int main(int argc, char** argv) +{ + return 0; +} diff --git a/listings/chap8/while_example/while_example.c b/listings/chap8/while_example/while_example.c new file mode 100755 index 0000000..eea739d --- /dev/null +++ b/listings/chap8/while_example/while_example.c @@ -0,0 +1,5 @@ +int x = 10; +while ( x != 0 ) { + puts("Hello"); + x = x - 1; +} diff --git a/listings/chap8/while_for_equiv/while_for_equiv.c b/listings/chap8/while_for_equiv/while_for_equiv.c new file mode 100755 index 0000000..12c1926 --- /dev/null +++ b/listings/chap8/while_for_equiv/while_for_equiv.c @@ -0,0 +1,13 @@ +int i; + +/* as a `while` loop */ +i = 0; +while ( i < 10 ) { + puts("Hello!"); + i = i + 1; +} + +/* as a `for` loop */ +for( i = 0; i < 10; i = i + 1 ) { + puts("Hello!"); +} diff --git a/listings/chap9/anon_no/anon_no.c b/listings/chap9/anon_no/anon_no.c new file mode 100755 index 0000000..386ae41 --- /dev/null +++ b/listings/chap9/anon_no/anon_no.c @@ -0,0 +1,12 @@ +union vec3d { + struct { + double x; + double y; + double z; + } named ; + double raw[3]; +}; + + +union vec3d vec; + diff --git a/listings/chap9/anon_struct/anon_struct.c b/listings/chap9/anon_struct/anon_struct.c new file mode 100755 index 0000000..0f7ef41 --- /dev/null +++ b/listings/chap9/anon_struct/anon_struct.c @@ -0,0 +1,10 @@ +union vec3d { + struct { + double x; + double y; + double z; + }; + double raw[3]; +}; + +union vec3d vec; diff --git a/listings/chap9/array_decl/array_decl.c b/listings/chap9/array_decl/array_decl.c new file mode 100755 index 0000000..96512fd --- /dev/null +++ b/listings/chap9/array_decl/array_decl.c @@ -0,0 +1,5 @@ +/* This array's size is computed by compiler */ +int arr[] = {1,2,3,4,5}; + +/* This array is initialized with zeros, its size is 256 bytes */ +long array[32] = {0}; diff --git a/listings/chap9/array_example_rw/array_example_rw.c b/listings/chap9/array_example_rw/array_example_rw.c new file mode 100755 index 0000000..1976843 --- /dev/null +++ b/listings/chap9/array_example_rw/array_example_rw.c @@ -0,0 +1,6 @@ +int myarray[1024]; +int y = myarray[64]; + +int first = myarray[0]; + +myarray[10] = 42; diff --git a/listings/chap9/array_param_size/array_param_size.c b/listings/chap9/array_param_size/array_param_size.c new file mode 100755 index 0000000..aaeb3e6 --- /dev/null +++ b/listings/chap9/array_param_size/array_param_size.c @@ -0,0 +1 @@ +int first( int array[10], size_t sz ) { ... } diff --git a/listings/chap9/array_param_size_static/array_param_size_static.c b/listings/chap9/array_param_size_static/array_param_size_static.c new file mode 100755 index 0000000..32bde75 --- /dev/null +++ b/listings/chap9/array_param_size_static/array_param_size_static.c @@ -0,0 +1 @@ +int fun(int array[static 10] ) {...} diff --git a/listings/chap9/beg1/beg1.c b/listings/chap9/beg1/beg1.c new file mode 100755 index 0000000..8294cc5 --- /dev/null +++ b/listings/chap9/beg1/beg1.c @@ -0,0 +1,11 @@ +#include +int array[] = {1,2,3,4,5}; + +int main( int argc, char** argv ) { + int i; + int sum; + for( i = 0; i < 5; i++ ) + sum = sum + array[i]; + printf("The sum is: %d\n", sum ); + return 0; +} diff --git a/listings/chap9/beg2/beg2.c b/listings/chap9/beg2/beg2.c new file mode 100755 index 0000000..ef29027 --- /dev/null +++ b/listings/chap9/beg2/beg2.c @@ -0,0 +1,11 @@ +#include +int array[] = {1,2,3,4,5}; + +int main( int argc, char** argv ) { + int i; + int sum = 0; + for( i = 0; i < 5; i++ ) + sum = sum + array[i]; + printf("The sum is: %d\n", sum ); + return 0; +} diff --git a/listings/chap9/beg3/beg3.c b/listings/chap9/beg3/beg3.c new file mode 100755 index 0000000..587f64a --- /dev/null +++ b/listings/chap9/beg3/beg3.c @@ -0,0 +1,16 @@ +#include +int array[] = {1,2,3,4,5}; + +void array_sum( void ) { + int i; + int sum = 0; + for( i = 0; i < 5; i++ ) + sum = sum + array[i]; + printf("The sum is: %d\n", sum ); + +} + +int main( int argc, char** argv ) { + array_sum(); + return 0; +} diff --git a/listings/chap9/beg4/beg4.c b/listings/chap9/beg4/beg4.c new file mode 100755 index 0000000..643ff5b --- /dev/null +++ b/listings/chap9/beg4/beg4.c @@ -0,0 +1,16 @@ +#include +int array[] = {1,2,3,4,5}; + +void array_sum( void ) { + int i; + int sum = 0; + for( i = 0; i < sizeof(array) / 4; i++ ) + sum = sum + array[i]; + printf("The sum is: %d\n", sum ); + +} + +int main( int argc, char** argv ) { + array_sum(); + return 0; +} diff --git a/listings/chap9/beg5/beg5.c b/listings/chap9/beg5/beg5.c new file mode 100755 index 0000000..8db44bc --- /dev/null +++ b/listings/chap9/beg5/beg5.c @@ -0,0 +1,15 @@ +#include +int array[] = {1,2,3,4,5}; + +void array_sum( void ) { + int i; + int sum = 0; + for( i = 0; i < sizeof(array) / sizeof(int); i++ ) + sum = sum + array[i]; + printf("The sum is: %d\n", sum ); +} + +int main( int argc, char** argv ) { + array_sum(); + return 0; +} diff --git a/listings/chap9/beg6/beg6.c b/listings/chap9/beg6/beg6.c new file mode 100755 index 0000000..e78924e --- /dev/null +++ b/listings/chap9/beg6/beg6.c @@ -0,0 +1,17 @@ +#include + +int array[] = {1,2,3,4,5}; + +void array_sum( void ) { + size_t i; + int sum = 0; + for( i = 0; i < sizeof(array) / sizeof(int); i++ ) + sum = sum + array[i]; + printf("The sum is: %d\n", sum ); +} + +int main( int argc, char** argv ) { + array_sum(); + return 0; +} + diff --git a/listings/chap9/beg7/beg7.c b/listings/chap9/beg7/beg7.c new file mode 100755 index 0000000..1c10d6e --- /dev/null +++ b/listings/chap9/beg7/beg7.c @@ -0,0 +1,16 @@ +#include + +int array[] = {1,2,3,4,5}; + +void array_sum( int* array, size_t count ) { + size_t i; + int sum = 0; + for( i = 0; i < count; i++ ) + sum = sum + array[i]; + printf("The sum is: %d\n", sum ); +} + +int main( int argc, char** argv ) { + array_sum(array, sizeof(array) / sizeof(int)); + return 0; +} diff --git a/listings/chap9/beg8/beg8.c b/listings/chap9/beg8/beg8.c new file mode 100755 index 0000000..1e2f954 --- /dev/null +++ b/listings/chap9/beg8/beg8.c @@ -0,0 +1,20 @@ +#include + +int g_array[] = {1,2,3,4,5}; + +int array_sum( int* array, size_t count ) { + size_t i; + int sum = 0; + for( i = 0; i < count; i++ ) + sum = sum + array[i]; + return sum; +} + +int main( int argc, char** argv ) { + printf( + "The sum is: %d\n", + array_sum(g_array, sizeof(g_array) / sizeof(int)) + ); + return 0; +} + diff --git a/listings/chap9/beg9/beg9.c b/listings/chap9/beg9/beg9.c new file mode 100755 index 0000000..a2cdf68 --- /dev/null +++ b/listings/chap9/beg9/beg9.c @@ -0,0 +1,19 @@ +#include + +const int g_array[] = {1,2,3,4,5}; + +int array_sum( int const* array, size_t count ) { + size_t i; + int sum = 0; + for( i = 0; i < count; i++ ) + sum = sum + array[i]; + return sum; +} + +int main( int argc, char** argv ) { + printf( + "The sum is: %d\n", + array_sum(g_array, sizeof(g_array) / sizeof(int)) + ); + return 0; +} diff --git a/listings/chap9/c_inclusion/c_inclusion.c b/listings/chap9/c_inclusion/c_inclusion.c new file mode 100755 index 0000000..c511960 --- /dev/null +++ b/listings/chap9/c_inclusion/c_inclusion.c @@ -0,0 +1,23 @@ +#include + +struct parent { + const char* field_parent; +}; + +struct child { + struct parent base; + const char* field_child; +}; + +void parent_print( struct parent* this ) { + printf( "%s\n", this->field_parent ); +} + +int main( int argc, char** argv ) { + struct child c; + c.base.field_parent = "parent"; + c.field_child = "child"; + parent_print( (struct parent*) &c ); + + return 0; +} diff --git a/listings/chap9/c_overload_11/c_overload_11.c b/listings/chap9/c_overload_11/c_overload_11.c new file mode 100755 index 0000000..e948f1c --- /dev/null +++ b/listings/chap9/c_overload_11/c_overload_11.c @@ -0,0 +1,16 @@ +#include + +#define print_fmt(x) (_Generic( (x), \ + int: "%d",\ + double: "%f",\ + default: "%x")) + +#define print(x) printf( print_fmt(x), x ); puts(""); + +int main(void) { + int x = 101; + double y = 42.42; + print(x); + print(y); + return 0; +} diff --git a/listings/chap9/c_parametric_polymorphism/c_parametric_polymorphism.c b/listings/chap9/c_parametric_polymorphism/c_parametric_polymorphism.c new file mode 100755 index 0000000..599ad9c --- /dev/null +++ b/listings/chap9/c_parametric_polymorphism/c_parametric_polymorphism.c @@ -0,0 +1,25 @@ +#include +#include + +#define pair(T) pair_##T +#define DEFINE_PAIR(T) struct pair(T) {\ + T fst;\ + T snd;\ +};\ +bool pair_##T##_any(struct pair(T) pair, bool (*predicate)(T)) {\ + return predicate(pair.fst) || predicate(pair.snd); \ +} + +#define any(T) pair_##T##_any + +DEFINE_PAIR(int) + + bool is_positive( int x ) { return x > 0; } + int main( int argc, char** argv ) { + struct pair(int) obj; + obj.fst = 1; + obj.snd = -1; + printf("%d\n", any(int)(obj, is_positive) ); + return 0; + } + diff --git a/listings/chap9/char_example/char_example.c b/listings/chap9/char_example/char_example.c new file mode 100755 index 0000000..739b283 --- /dev/null +++ b/listings/chap9/char_example/char_example.c @@ -0,0 +1,3 @@ +char number = 5; +char symbol_code = 'x'; +char null_terminator = '\0'; diff --git a/listings/chap9/const_cast/const_cast.c b/listings/chap9/const_cast/const_cast.c new file mode 100755 index 0000000..6d9b5fd --- /dev/null +++ b/listings/chap9/const_cast/const_cast.c @@ -0,0 +1,9 @@ +#include + +int main(void) { + const int x = 10; + *( (int*)&x ) = 30; + + printf( "%d\n", x ); + return 0; +} diff --git a/listings/chap9/const_def/const_def.c b/listings/chap9/const_def/const_def.c new file mode 100755 index 0000000..905b1c7 --- /dev/null +++ b/listings/chap9/const_def/const_def.c @@ -0,0 +1,16 @@ +int a; +a = 42 ; /* ok */ + +... + +const int a; /* compilation error */ + +... + +const int a = 42; /* ok */ +a = 99; /* compilation error, should not change constant value */ + + + +int const a = 42; /* ok */ +const int b = 99; /* ok, const int === int const */ diff --git a/listings/chap9/const_discard/const_discard.c b/listings/chap9/const_discard/const_discard.c new file mode 100755 index 0000000..80b582e --- /dev/null +++ b/listings/chap9/const_discard/const_discard.c @@ -0,0 +1,8 @@ +int x; +int y; + +int const* px = &x; +int * py = &y; + +py = px; /* Error, const qualifier is discarded */ +px = py; /* OK */ diff --git a/listings/chap9/designated_initializers_arrays/designated_initializers_arrays.c b/listings/chap9/designated_initializers_arrays/designated_initializers_arrays.c new file mode 100755 index 0000000..f025595 --- /dev/null +++ b/listings/chap9/designated_initializers_arrays/designated_initializers_arrays.c @@ -0,0 +1,16 @@ +int whitespace[256] = { + [' ' ] = 1, + ['\t'] = 1, + ['\f'] = 1, + ['\n'] = 1, + ['\r'] = 1 }; + +enum colors { + RED, + GREEN, + BLUE, + MAGENTA, + YELLOW +}; + +int good[5] = { [ RED ] = 1, [ MAGENTA ] = 1 }; diff --git a/listings/chap9/enum_example/enum_example.c b/listings/chap9/enum_example/enum_example.c new file mode 100755 index 0000000..2d24bef --- /dev/null +++ b/listings/chap9/enum_example/enum_example.c @@ -0,0 +1,11 @@ +enum light { + RED, + RED_AND_YELLOW, + YELLOW, + GREEN, + NOTHING +}; + +... +enum light l = nothing; +... diff --git a/listings/chap9/fun_array1/fun_array1.c b/listings/chap9/fun_array1/fun_array1.c new file mode 100755 index 0000000..3262806 --- /dev/null +++ b/listings/chap9/fun_array1/fun_array1.c @@ -0,0 +1,4 @@ +int first (int array[], size_t sz ) { + if ( sz == 0 ) return -1; + return array[0]; +} diff --git a/listings/chap9/fun_array2/fun_array2.c b/listings/chap9/fun_array2/fun_array2.c new file mode 100755 index 0000000..f272d98 --- /dev/null +++ b/listings/chap9/fun_array2/fun_array2.c @@ -0,0 +1,4 @@ +int first (int array*, size_t sz ) { + if ( sz == 0 ) return -1; + return *array; +} diff --git a/listings/chap9/fun_array3/fun_array3.c b/listings/chap9/fun_array3/fun_array3.c new file mode 100755 index 0000000..c1d4237 --- /dev/null +++ b/listings/chap9/fun_array3/fun_array3.c @@ -0,0 +1,4 @@ +int first (int array*, size_t sz ) { + if ( sz == 0 ) return -1; + return array[0]; +} diff --git a/listings/chap9/fun_ptr_diff/fun_ptr_diff.c b/listings/chap9/fun_ptr_diff/fun_ptr_diff.c new file mode 100755 index 0000000..c59e230 --- /dev/null +++ b/listings/chap9/fun_ptr_diff/fun_ptr_diff.c @@ -0,0 +1,27 @@ +#include + +double g( int number ) { return 0.5 + number; } + +void fun( double (f)(int) ) { + printf(" f: %p\n", &f ); +} + +void fun_( double (*f)(int) ) { + printf("*f: %p\n", &f ); +} + +void arr( int arr[] ) { + printf("arr[]: %p \n", arr ); +} +void arr_( int* arr ) { + printf("arr* : %p \n", arr ); +} + +int main( void ) { + int data[10]; + fun( g ); + fun_( g ); + arr( data ); + arr_( data ); + return 0; +} diff --git a/listings/chap9/fun_type_example/fun_type_example.c b/listings/chap9/fun_type_example/fun_type_example.c new file mode 100755 index 0000000..f9a1f70 --- /dev/null +++ b/listings/chap9/fun_type_example/fun_type_example.c @@ -0,0 +1,12 @@ +#include + +double g( int number ) { return 0.5 + number; } + +double apply( double (f)(int), int x ) { + return f( x ) ; +} + +int main( void ) { + printf( "%f\n", apply( g, 10 ) ); + return 0; +} diff --git a/listings/chap9/fun_type_example_alt/fun_type_example_alt.c b/listings/chap9/fun_type_example_alt/fun_type_example_alt.c new file mode 100755 index 0000000..0c10271 --- /dev/null +++ b/listings/chap9/fun_type_example_alt/fun_type_example_alt.c @@ -0,0 +1,12 @@ +#include + +double g( int number ) { return 0.5 + number; } + +double apply( double (*f)(int), int x ) { + return f( x ) ; +} + +int main( void ) { + printf( "%f\n", apply( g, 10 ) ); + return 0; +} diff --git a/listings/chap9/fun_types_decl/fun_types_decl.c b/listings/chap9/fun_types_decl/fun_types_decl.c new file mode 100755 index 0000000..42d0c8d --- /dev/null +++ b/listings/chap9/fun_types_decl/fun_types_decl.c @@ -0,0 +1,9 @@ +typedef double (proc)(int); + +/* declaration */ +proc myproc; + +/* ... */ + +/* definition */ +double myproc( int x ) { return 42.0 + x; } diff --git a/listings/chap9/int_float_conv/int_float_conv.c b/listings/chap9/int_float_conv/int_float_conv.c new file mode 100755 index 0000000..b5fe4ce --- /dev/null +++ b/listings/chap9/int_float_conv/int_float_conv.c @@ -0,0 +1,3 @@ +int i; +float f; +double d = f + i; diff --git a/listings/chap9/int_promotion_pitfall/int_promotion_pitfall.c b/listings/chap9/int_promotion_pitfall/int_promotion_pitfall.c new file mode 100755 index 0000000..eb6b5dd --- /dev/null +++ b/listings/chap9/int_promotion_pitfall/int_promotion_pitfall.c @@ -0,0 +1,14 @@ +/* The lesser types */ +unsigned char x = 100, y = 100, z = 100; +unsigned char r = x + y + z; /* will give you 300 % 256 = 44 */ + +unsigned int r_int = x + y + z; /* equals to 300, because the promotion to + integers is performed first */ + +/* Now with the greater types */ + +unsigned int x = 1e9, y = 2e9, z = 3e9; + +unsigned int r_int = x + y + z; /* 1705032704 equals 6000000000 % (2^32) */ + +unsigned long r_long = x + y + z; /* the same result: 1705032704 */ diff --git a/listings/chap9/macro_concat/macro_concat.c b/listings/chap9/macro_concat/macro_concat.c new file mode 100755 index 0000000..743f158 --- /dev/null +++ b/listings/chap9/macro_concat/macro_concat.c @@ -0,0 +1,7 @@ +#define x1 "Hello" +#define x2 " World" + +#define str(i) x##i + +puts( str(1) ); /* str(1) -> x1 -> "Hello" */ +puts( str(2) ); /* str(2) -> x2 -> " World" */ diff --git a/listings/chap9/macro_define_pair/macro_define_pair.c b/listings/chap9/macro_define_pair/macro_define_pair.c new file mode 100755 index 0000000..59013ac --- /dev/null +++ b/listings/chap9/macro_define_pair/macro_define_pair.c @@ -0,0 +1,7 @@ +struct pair_int { + int fst; + int snd; +}; +bool pair_int_any(struct pair_int pair, bool (*predicate)(int)) { + return predicate(pair.fst) || predicate(pair.snd); +} diff --git a/listings/chap9/macro_str/macro_str.c b/listings/chap9/macro_str/macro_str.c new file mode 100755 index 0000000..49befc4 --- /dev/null +++ b/listings/chap9/macro_str/macro_str.c @@ -0,0 +1,4 @@ +#define mystr hello +#define res #mystr + +puts( res ); /* will be replaced with `puts("hello")` diff --git a/listings/chap9/main_revisited/main_revisited.c b/listings/chap9/main_revisited/main_revisited.c new file mode 100755 index 0000000..86f60f5 --- /dev/null +++ b/listings/chap9/main_revisited/main_revisited.c @@ -0,0 +1,8 @@ +#include + +int main( int argc, char* argv[] ) { + int i; + for( i = 0; i < argc; i++ ) + puts( argv[i] ); + return 0; +} diff --git a/listings/chap9/pixel/pixel.c b/listings/chap9/pixel/pixel.c new file mode 100755 index 0000000..990f6f3 --- /dev/null +++ b/listings/chap9/pixel/pixel.c @@ -0,0 +1,6 @@ +union pixel { + struct { + char a,b,c; + }; + char at[3]; +}; diff --git a/listings/chap9/ptr_deref/ptr_deref.c b/listings/chap9/ptr_deref/ptr_deref.c new file mode 100755 index 0000000..93db9d5 --- /dev/null +++ b/listings/chap9/ptr_deref/ptr_deref.c @@ -0,0 +1,6 @@ +int x = 10; +int* px = &x; /* Took address of `x` and assigned it to `px` */ + +*px = 42; /* We modified `x` here! */ +printf( "*px = %d\n", *px ); /* outputs: '*px = 42' */ +printf( "x = %d\n", x ); /* outputs: 'x = 42' */ diff --git a/listings/chap9/size_int_difference/size_int_difference.c b/listings/chap9/size_int_difference/size_int_difference.c new file mode 100755 index 0000000..9524d98 --- /dev/null +++ b/listings/chap9/size_int_difference/size_int_difference.c @@ -0,0 +1,6 @@ +size_t s; +int i; +... +for( i = 0; i < s; i++ ) { + ... +} diff --git a/listings/chap9/sizeof_array/sizeof_array.c b/listings/chap9/sizeof_array/sizeof_array.c new file mode 100755 index 0000000..f462842 --- /dev/null +++ b/listings/chap9/sizeof_array/sizeof_array.c @@ -0,0 +1,9 @@ +#include + +long array[] = { 1, 2, 3 }; + +int main(void) { + printf( "%zu \n", sizeof( array ) ); /* output: 24 */ + printf( "%zu \n", sizeof( array[0] ) ); /* output: 8 */ + return 0; +} diff --git a/listings/chap9/sizeof_array_fun/sizeof_array_fun.c b/listings/chap9/sizeof_array_fun/sizeof_array_fun.c new file mode 100755 index 0000000..c6df403 --- /dev/null +++ b/listings/chap9/sizeof_array_fun/sizeof_array_fun.c @@ -0,0 +1,9 @@ +#include +const int arr[] = {1, 2, 3, 4}; +void f(int const arr[]) { + printf("%zu\n", sizeof( arr ) ); +} +int main( void ) { + f(arr); + return 0; +} diff --git a/listings/chap9/string_literal_breaks/string_literal_breaks.c b/listings/chap9/string_literal_breaks/string_literal_breaks.c new file mode 100755 index 0000000..08e9bfa --- /dev/null +++ b/listings/chap9/string_literal_breaks/string_literal_breaks.c @@ -0,0 +1,2 @@ +char const* hello = "Hel" "lo" +"world!"; diff --git a/listings/chap9/struct_anon/struct_anon.c b/listings/chap9/struct_anon/struct_anon.c new file mode 100755 index 0000000..26d623e --- /dev/null +++ b/listings/chap9/struct_anon/struct_anon.c @@ -0,0 +1,3 @@ +struct { int a; char b; } d; +d.a = 0; +d.b = 'k'; diff --git a/listings/chap9/struct_c99_init/struct_c99_init.c b/listings/chap9/struct_c99_init/struct_c99_init.c new file mode 100755 index 0000000..effa151 --- /dev/null +++ b/listings/chap9/struct_c99_init/struct_c99_init.c @@ -0,0 +1,6 @@ +struct pair { + char a; + char b; +}; + +struct pair st = { .a = 'a',.b = 'b' }; diff --git a/listings/chap9/struct_init/struct_init.c b/listings/chap9/struct_init/struct_init.c new file mode 100755 index 0000000..7832c0e --- /dev/null +++ b/listings/chap9/struct_init/struct_init.c @@ -0,0 +1,3 @@ +struct S {char const* name; int value; }; +... +struct S new_s = { "myname", 4 }; diff --git a/listings/chap9/struct_named/struct_named.c b/listings/chap9/struct_named/struct_named.c new file mode 100755 index 0000000..d97fd1f --- /dev/null +++ b/listings/chap9/struct_named/struct_named.c @@ -0,0 +1,10 @@ +struct pair { + int a; + int b; +}; + +... + +struct pair d; +d.a = 0; +d.b = 1; diff --git a/listings/chap9/struct_namespace/struct_namespace.c b/listings/chap9/struct_namespace/struct_namespace.c new file mode 100755 index 0000000..36291fb --- /dev/null +++ b/listings/chap9/struct_namespace/struct_namespace.c @@ -0,0 +1,10 @@ +typedef unsigned int type; +struct type { + char c; +}; + +int main( int argc, char** argv ) { + struct type st; + type t; + return 0; +} diff --git a/listings/chap9/struct_zero/struct_zero.c b/listings/chap9/struct_zero/struct_zero.c new file mode 100755 index 0000000..93d9035 --- /dev/null +++ b/listings/chap9/struct_zero/struct_zero.c @@ -0,0 +1,4 @@ +struct pair { int a; int b; }; + +... +struct pair p = { 0 }; diff --git a/listings/chap9/type_cast/type_cast.c b/listings/chap9/type_cast/type_cast.c new file mode 100755 index 0000000..103e861 --- /dev/null +++ b/listings/chap9/type_cast/type_cast.c @@ -0,0 +1,6 @@ +int a = 4; + +double b = 10.5 * (double)a; /* now a is a double */ + +int b = 129; +char k = (char)b; //??? diff --git a/listings/chap9/typedef_bad_fun_ptr/typedef_bad_fun_ptr.c b/listings/chap9/typedef_bad_fun_ptr/typedef_bad_fun_ptr.c new file mode 100755 index 0000000..dcd4579 --- /dev/null +++ b/listings/chap9/typedef_bad_fun_ptr/typedef_bad_fun_ptr.c @@ -0,0 +1 @@ +typedef void(*proc)(void); diff --git a/listings/chap9/typedef_example/typedef_example.c b/listings/chap9/typedef_example/typedef_example.c new file mode 100755 index 0000000..e329c93 --- /dev/null +++ b/listings/chap9/typedef_example/typedef_example.c @@ -0,0 +1 @@ +typedef unsigned short int mytype_t; diff --git a/listings/chap9/typedef_good_fun_ptr/typedef_good_fun_ptr.c b/listings/chap9/typedef_good_fun_ptr/typedef_good_fun_ptr.c new file mode 100755 index 0000000..34dc3c0 --- /dev/null +++ b/listings/chap9/typedef_good_fun_ptr/typedef_good_fun_ptr.c @@ -0,0 +1,5 @@ +typedef void(proc)(void); + +... + +proc* my_ptr = &some_proc; diff --git a/listings/chap9/typedef_struct_simple/typedef_struct_simple.c b/listings/chap9/typedef_struct_simple/typedef_struct_simple.c new file mode 100755 index 0000000..5d0e07e --- /dev/null +++ b/listings/chap9/typedef_struct_simple/typedef_struct_simple.c @@ -0,0 +1 @@ +typedef struct type type; diff --git a/listings/chap9/union_example/union_example.c b/listings/chap9/union_example/union_example.c new file mode 100755 index 0000000..f04a75c --- /dev/null +++ b/listings/chap9/union_example/union_example.c @@ -0,0 +1,8 @@ +union dword { + int integer; + short shorts[2]; +}; + +... +dword test; +test.integer = 0xAABBCCDD; diff --git a/listings/chap9/union_guarantee/union_guarantee.c b/listings/chap9/union_guarantee/union_guarantee.c new file mode 100755 index 0000000..08d0ecc --- /dev/null +++ b/listings/chap9/union_guarantee/union_guarantee.c @@ -0,0 +1,16 @@ +struct sa { + int x; + char y; + char z; +}; + +struct sb { + int x; + char y; + int notz; +}; + +union test { + struct sa as_sa; + struct sb as_sb; +}; diff --git a/listings/chap9/void_deref/void_deref.c b/listings/chap9/void_deref/void_deref.c new file mode 100755 index 0000000..f036b96 --- /dev/null +++ b/listings/chap9/void_deref/void_deref.c @@ -0,0 +1,4 @@ +int a = 10; +void* pa = &a; + +printf("%d\n", *( (int*) pa) ); diff --git a/listings/start_tests.sh b/listings/start_tests.sh new file mode 100755 index 0000000..231b356 --- /dev/null +++ b/listings/start_tests.sh @@ -0,0 +1,14 @@ +#!/bin/bash +TESTDIR=tests + +rm -rf "$TESTDIR" +mkdir tests +for testprog in `cat tests_asm` +do + mkdir "$TESTDIR/$testprog" + cp "$testprog" "$TESTDIR/$testprog/$testprog" + nasm "$testprog" -felf64 -o "$TESTDIR/$testprog/$testprog.o" && ld "$TESTDIR/$testprog/$testprog.o" -o "$TESTDIR/$testprog/$testprog" + chmod u+x "$TESTDIR/$testprog/$testprog" + "./$TESTDIR/$testprog/$testprog" + echo "> $testprog Terminated with code" $? +done diff --git a/listings/tests/strlen.asm/strlen.asm b/listings/tests/strlen.asm/strlen.asm new file mode 100755 index 0000000000000000000000000000000000000000..e42fd5e12f8bfe3a05d39616dfb81d043d2cd380 GIT binary patch literal 1024 zcmb_byGjF55S?tyLlBIeU}3Bb2mu?hh>}KG!NSIR-I(&PFo;l~9nc4f;`-9^{CzBxzhxSR>km^>7-$Z@KQq^|J;rTpe ztv5HF;;61H#<4OWQQ0ceBhL@?F`Zc*Sg?!;h&*?D)UOrDzMUngP z`c&i0<(%I*Zw41c)$p!u{05`x#dw9t1h}Zv;I}9&(>d8{V~;dOZDfJzQcNnzZ2(XZT#A^x@NY^&S7K^%0N#4f*Q$nzRuh&Zr2?#c8&j5V%-yCmgsP6Mr7Q3R9_ zC~h!HepWfo6Zdj@|6;>}`T#2&AQzh8M9F4S