diff --git a/asm-talk/.gitignore b/asm-talk/.gitignore new file mode 100644 index 0000000..e43b0f9 --- /dev/null +++ b/asm-talk/.gitignore @@ -0,0 +1 @@ +.DS_Store diff --git a/asm-talk/README.md b/asm-talk/README.md new file mode 100644 index 0000000..e7eff0f --- /dev/null +++ b/asm-talk/README.md @@ -0,0 +1,53 @@ +# Notes for the Programming Guild Presentation + +Some starting knowledge +Overview of the implementation + +building binaries - as, ld and the gcc toolkit + +Gas files + +Opcodes + + + +Entry points + +Reading from the process arguments and converting to a numeric value + +The stack + +GDB debugging - live demo + +Getting the length of our argument on the command line + +Making things easier to understand using function calls + + +Converting a string to a number + +Register sizes and layout + - alu, registers, memory + +Processing the string + +The actual Fibonacci algorithm + +Creating the stack space for our array + +The Fibonacci logic in assembly +Setting up our variables +Array memory allocation + +Variable initialisation + +Indexed memory + +Running the loop to completion +Calculating the sequence + +Printing our result + + + + diff --git a/asm-talk/Will van Ketwich - Fibonacci Assembly Slides.pdf b/asm-talk/Will van Ketwich - Fibonacci Assembly Slides.pdf new file mode 100644 index 0000000..a51e825 Binary files /dev/null and b/asm-talk/Will van Ketwich - Fibonacci Assembly Slides.pdf differ diff --git a/asm-talk/asm_talk.key b/asm-talk/asm_talk.key new file mode 100644 index 0000000..5ff1299 Binary files /dev/null and b/asm-talk/asm_talk.key differ diff --git a/asm-talk/css/default.css b/asm-talk/css/default.css new file mode 100644 index 0000000..5c41e86 --- /dev/null +++ b/asm-talk/css/default.css @@ -0,0 +1,142 @@ +@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic); +/** + * Default theme for reveal.js. + * + * Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se + */ +@font-face { + font-family: 'League Gothic'; + src: url("../font/league_gothic-webfont.eot"); + src: url("../font/league_gothic-webfont.eot?#iefix") format("embedded-opentype"), url("../font/league_gothic-webfont.woff") format("woff"), url("../font/league_gothic-webfont.ttf") format("truetype"); + font-weight: normal; + font-style: normal; } + +/********************************************* + * GLOBAL STYLES + *********************************************/ +body { + background: #1c1e20; + background: -moz-radial-gradient(center, circle cover, #555a5f 0%, #1c1e20 100%); + background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, #555a5f), color-stop(100%, #1c1e20)); + background: -webkit-radial-gradient(center, circle cover, #555a5f 0%, #1c1e20 100%); + background: -o-radial-gradient(center, circle cover, #555a5f 0%, #1c1e20 100%); + background: -ms-radial-gradient(center, circle cover, #555a5f 0%, #1c1e20 100%); + background: radial-gradient(center, circle cover, #555a5f 0%, #1c1e20 100%); + background-color: #2b2b2b; } + +.reveal { + font-family: "Lato", sans-serif; + font-size: 36px; + font-weight: 200; + letter-spacing: -0.02em; + color: #eeeeee; } + +::selection { + color: white; + background: #ff5e99; + text-shadow: none; } + +/********************************************* + * HEADERS + *********************************************/ +.reveal h1, +.reveal h2, +.reveal h3, +.reveal h4, +.reveal h5, +.reveal h6 { + margin: 0 0 20px 0; + color: #eeeeee; + font-family: "League Gothic", Impact, sans-serif; + line-height: 0.9em; + letter-spacing: 0.02em; + text-transform: uppercase; + text-shadow: 0px 0px 6px rgba(0, 0, 0, 0.2); } + +.reveal h1 { + text-shadow: 0 1px 0 #cccccc, 0 2px 0 #c9c9c9, 0 3px 0 #bbbbbb, 0 4px 0 #b9b9b9, 0 5px 0 #aaaaaa, 0 6px 1px rgba(0, 0, 0, 0.1), 0 0 5px rgba(0, 0, 0, 0.1), 0 1px 3px rgba(0, 0, 0, 0.3), 0 3px 5px rgba(0, 0, 0, 0.2), 0 5px 10px rgba(0, 0, 0, 0.25), 0 20px 20px rgba(0, 0, 0, 0.15); } + +/********************************************* + * LINKS + *********************************************/ +.reveal a:not(.image) { + color: #13daec; + text-decoration: none; + -webkit-transition: color .15s ease; + -moz-transition: color .15s ease; + -ms-transition: color .15s ease; + -o-transition: color .15s ease; + transition: color .15s ease; } + +.reveal a:not(.image):hover { + color: #71e9f4; + text-shadow: none; + border: none; } + +.reveal .roll span:after { + color: #fff; + background: #0d99a5; } + +/********************************************* + * IMAGES + *********************************************/ +.reveal section img { + margin: 15px 0px; + background: rgba(255, 255, 255, 0.12); + border: 4px solid #eeeeee; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); + -webkit-transition: all .2s linear; + -moz-transition: all .2s linear; + -ms-transition: all .2s linear; + -o-transition: all .2s linear; + transition: all .2s linear; } + +.reveal a:hover img { + background: rgba(255, 255, 255, 0.2); + border-color: #13daec; + box-shadow: 0 0 20px rgba(0, 0, 0, 0.55); } + +/********************************************* + * NAVIGATION CONTROLS + *********************************************/ +.reveal .controls div.navigate-left, +.reveal .controls div.navigate-left.enabled { + border-right-color: #13daec; } + +.reveal .controls div.navigate-right, +.reveal .controls div.navigate-right.enabled { + border-left-color: #13daec; } + +.reveal .controls div.navigate-up, +.reveal .controls div.navigate-up.enabled { + border-bottom-color: #13daec; } + +.reveal .controls div.navigate-down, +.reveal .controls div.navigate-down.enabled { + border-top-color: #13daec; } + +.reveal .controls div.navigate-left.enabled:hover { + border-right-color: #71e9f4; } + +.reveal .controls div.navigate-right.enabled:hover { + border-left-color: #71e9f4; } + +.reveal .controls div.navigate-up.enabled:hover { + border-bottom-color: #71e9f4; } + +.reveal .controls div.navigate-down.enabled:hover { + border-top-color: #71e9f4; } + +/********************************************* + * PROGRESS BAR + *********************************************/ +.reveal .progress { + background: rgba(0, 0, 0, 0.2); } + +.reveal .progress span { + background: #13daec; + -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + -moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + -ms-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + -o-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } diff --git a/asm-talk/css/logo.png b/asm-talk/css/logo.png new file mode 100644 index 0000000..cc3e49d Binary files /dev/null and b/asm-talk/css/logo.png differ diff --git a/asm-talk/css/overrides.css b/asm-talk/css/overrides.css new file mode 100644 index 0000000..881e608 --- /dev/null +++ b/asm-talk/css/overrides.css @@ -0,0 +1,151 @@ + +h1,h2,h3 { + font-family: verdana; + text-transform:none!important; +} + +.em { + color:#00C0F7!important; +} + +.em3 { + color:#6AB825!important +} + +.em4 { + color:#ED9D13!important +} + +.em2 { + color:#ED9D13!important +} + +.em5 { + color:maroon!important; +} + + +h1 { + font-size:2.5em!important; + text-shadow:none!important; +} + +h2 { + font-size:2.0em!important; +} + +html { + background:url('pattern.png') repeat; +} + +body { + background-image:none; + background: -moz-linear-gradient(top, rgba(0,0,0,0.1) 30%, rgba(0,0,0,1) 100%); /* FF3.6+ */ + background: -webkit-gradient(linear, left top, left bottom, color-stop(30%,rgba(0,0,0,0.1)), color-stop(100%,rgba(0,0,0,1))); /* Chrome,Safari4+ */ + background: -webkit-linear-gradient(top, rgba(0,0,0,0.1) 30%,rgba(0,0,0,1) 100%); /* Chrome10+,Safari5.1+ */ + background: -o-linear-gradient(top, rgba(0,0,0,0.1) 30%,rgba(0,0,0,1) 100%); /* Opera 11.10+ */ + background: -ms-linear-gradient(top, rgba(0,0,0,0.1) 30%,rgba(0,0,0,1) 100%); /* IE10+ */ + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#1a000000', endColorstr='#000000',GradientType=0 ); /* IE6-9 */ +} + +.reveal { + z-index:1500; +} + +#me { + border: 0; + margin-top: -20px; + background: none; + margin-bottom: -50px; +} + +#logo { + border:0; + background:url('ruby.png') no-repeat top; + height: 300px; + margin-top:-20px; + z-index:100; + position:relative; +} +.logo { + border-radius: 10px; +} + +#logo:after { + content:""; + position:absolute; + top:0; + left:0; + right:0; + bottom:0; + background: -moz-linear-gradient(top, rgba(0,0,0,0.1) 70%, rgba(0,0,0,1) 100%); /* FF3.6+ */ + background: -webkit-gradient(linear, left top, left bottom, color-stop(70%,rgba(0,0,0,0.1)), color-stop(100%,rgba(0,0,0,1))); /* Chrome,Safari4+ */ + background: -webkit-linear-gradient(top, rgba(0,0,0,0.1) 70%,rgba(0,0,0,1) 100%); /* Chrome10+,Safari5.1+ */ + background: -o-linear-gradient(top, rgba(0,0,0,0.1) 70%,rgba(0,0,0,1) 100%); /* Opera 11.10+ */ + background: -ms-linear-gradient(top, rgba(0,0,0,0.1) 70%,rgba(0,0,0,1) 100%); /* IE10+ */ + background: linear-gradient(to bottom, rgba(0,0,0,0.1) 70%,rgba(0,0,0,1) 100%); /* W3C */ + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#1a000000', endColorstr='#000000',GradientType=0 ); /* IE6-9 */ +} + +.existing-example { + margin:30px auto!important; + background:url('existing-example.png') no-repeat center top; + height:300px; + display:block; +} +.animated-example { + margin:30px auto!important; + background:url('animated-example.png') no-repeat center top; + height:300px; + display:block; +} + +#anchor { + position:fixed; + bottom:20px; + left:20px; + font-size:2em; + background:rgba(0,0,0,1); + padding:10px; + text-decoration:none; +} + +.big-code * { + font-size:25px!important; + line-height:30px!important; +} +.yom-table { + width:100%; + border-collapse:collapse; +} + +.yom-table td, +.yom-table th { + width:50%; + text-align:center!important; + border:5px solid #222; + padding:10px; +} +.yom-table th { + background:#00566f!important +} +.yom-table td { + background:rgba(50,50,50,0.8); +} +#animation-inputs th.first, +#animation-inputs td.first { + width:30%!important; +} +#animation-members th.first, +#animation-members td.first { + width:20%!important; +} + +.align-center { + text-align:center; +} + +.joybox { + background: url(../img/cat-intro2.png) no-repeat center 50px, url("../img/bg-intro.png") no-repeat center; + min-height: 600px; +} diff --git a/asm-talk/css/paper.css b/asm-talk/css/paper.css new file mode 100644 index 0000000..f902dea --- /dev/null +++ b/asm-talk/css/paper.css @@ -0,0 +1,176 @@ +/* Default Print Stylesheet Template + by Rob Glazebrook of CSSnewbie.com + Last Updated: June 4, 2008 + + Feel free (nay, compelled) to edit, append, and + manipulate this file as you see fit. */ + + +/* SECTION 1: Set default width, margin, float, and + background. This prevents elements from extending + beyond the edge of the printed page, and prevents + unnecessary background images from printing */ +body { + background: #fff; + font-size: 13pt; + width: auto; + height: auto; + border: 0; + margin: 0 5%; + padding: 0; + float: none !important; + overflow: visible; +} +html { + background: #fff; + width: auto; + height: auto; + overflow: visible; +} + +/* SECTION 2: Remove any elements not needed in print. + This would include navigation, ads, sidebars, etc. */ +.nestedarrow, +.controls, +.reveal .progress, +.reveal.overview, +.fork-reveal, +.share-reveal, +.state-background { + display: none !important; +} + +/* SECTION 3: Set body font face, size, and color. + Consider using a serif font for readability. */ +body, p, td, li, div, a { + font-size: 16pt!important; + font-family: Georgia, "Times New Roman", Times, serif !important; + color: #000; +} + +/* SECTION 4: Set heading font face, sizes, and color. + Diffrentiate your headings from your body text. + Perhaps use a large sans-serif for distinction. */ +h1,h2,h3,h4,h5,h6 { + color: #000!important; + height: auto; + line-height: normal; + font-family: Georgia, "Times New Roman", Times, serif !important; + text-shadow: 0 0 0 #000 !important; + text-align: left; + letter-spacing: normal; +} +/* Need to reduce the size of the fonts for printing */ +h1 { font-size: 26pt !important; } +h2 { font-size: 22pt !important; } +h3 { font-size: 20pt !important; } +h4 { font-size: 20pt !important; font-variant: small-caps; } +h5 { font-size: 19pt !important; } +h6 { font-size: 18pt !important; font-style: italic; } + +/* SECTION 5: Make hyperlinks more usable. + Ensure links are underlined, and consider appending + the URL to the end of the link for usability. */ +a:link, +a:visited { + color: #000 !important; + font-weight: bold; + text-decoration: underline; +} +/* +.reveal a:link:after, +.reveal a:visited:after { + content: " (" attr(href) ") "; + color: #222 !important; + font-size: 90%; +} +*/ + + +/* SECTION 6: more reveal.js specific additions by @skypanther */ +ul, ol, div, p { + visibility: visible; + position: static; + width: auto; + height: auto; + display: block; + overflow: visible; + margin: auto; + text-align: left !important; +} +.reveal .slides { + position: static; + width: auto; + height: auto; + + left: auto; + top: auto; + margin-left: auto; + margin-top: auto; + padding: auto; + + overflow: visible; + display: block; + + text-align: center; + -webkit-perspective: none; + -moz-perspective: none; + -ms-perspective: none; + perspective: none; + + -webkit-perspective-origin: 50% 50%; /* there isn't a none/auto value but 50-50 is the default */ + -moz-perspective-origin: 50% 50%; + -ms-perspective-origin: 50% 50%; + perspective-origin: 50% 50%; +} +.reveal .slides>section, +.reveal .slides>section>section { + + visibility: visible !important; + position: static !important; + width: 90% !important; + height: auto !important; + display: block !important; + overflow: visible !important; + + left: 0% !important; + top: 0% !important; + margin-left: 0px !important; + margin-top: 0px !important; + padding: 20px 0px !important; + + opacity: 1 !important; + + -webkit-transform-style: flat !important; + -moz-transform-style: flat !important; + -ms-transform-style: flat !important; + transform-style: flat !important; + + -webkit-transform: none !important; + -moz-transform: none !important; + -ms-transform: none !important; + transform: none !important; +} +.reveal section { + page-break-after: always !important; + display: block !important; +} +.reveal section .fragment { + opacity: 1 !important; + visibility: visible !important; + + -webkit-transform: none !important; + -moz-transform: none !important; + -ms-transform: none !important; + transform: none !important; +} +.reveal section:last-of-type { + page-break-after: avoid !important; +} +.reveal section img { + display: block; + margin: 15px 0px; + background: rgba(255,255,255,1); + border: 1px solid #666; + box-shadow: none; +} \ No newline at end of file diff --git a/asm-talk/css/pattern.png b/asm-talk/css/pattern.png new file mode 100644 index 0000000..cdfde09 Binary files /dev/null and b/asm-talk/css/pattern.png differ diff --git a/asm-talk/css/print/paper.css b/asm-talk/css/print/paper.css new file mode 100644 index 0000000..893184d --- /dev/null +++ b/asm-talk/css/print/paper.css @@ -0,0 +1,176 @@ +/* Default Print Stylesheet Template + by Rob Glazebrook of CSSnewbie.com + Last Updated: June 4, 2008 + + Feel free (nay, compelled) to edit, append, and + manipulate this file as you see fit. */ + + +/* SECTION 1: Set default width, margin, float, and + background. This prevents elements from extending + beyond the edge of the printed page, and prevents + unnecessary background images from printing */ +body { + background: #fff; + font-size: 13pt; + width: auto; + height: auto; + border: 0; + margin: 0 5%; + padding: 0; + float: none !important; + overflow: visible; +} +html { + background: #fff; + width: auto; + height: auto; + overflow: visible; +} + +/* SECTION 2: Remove any elements not needed in print. + This would include navigation, ads, sidebars, etc. */ +.nestedarrow, +.controls, +.reveal .progress, +.reveal.overview, +.fork-reveal, +.share-reveal, +.state-background { + display: none !important; +} + +/* SECTION 3: Set body font face, size, and color. + Consider using a serif font for readability. */ +body, p, td, li, div, a { + font-size: 16pt!important; + font-family: Georgia, "Times New Roman", Times, serif !important; + color: #000; +} + +/* SECTION 4: Set heading font face, sizes, and color. + Differentiate your headings from your body text. + Perhaps use a large sans-serif for distinction. */ +h1,h2,h3,h4,h5,h6 { + color: #000!important; + height: auto; + line-height: normal; + font-family: Georgia, "Times New Roman", Times, serif !important; + text-shadow: 0 0 0 #000 !important; + text-align: left; + letter-spacing: normal; +} +/* Need to reduce the size of the fonts for printing */ +h1 { font-size: 26pt !important; } +h2 { font-size: 22pt !important; } +h3 { font-size: 20pt !important; } +h4 { font-size: 20pt !important; font-variant: small-caps; } +h5 { font-size: 19pt !important; } +h6 { font-size: 18pt !important; font-style: italic; } + +/* SECTION 5: Make hyperlinks more usable. + Ensure links are underlined, and consider appending + the URL to the end of the link for usability. */ +a:link, +a:visited { + color: #000 !important; + font-weight: bold; + text-decoration: underline; +} +/* +.reveal a:link:after, +.reveal a:visited:after { + content: " (" attr(href) ") "; + color: #222 !important; + font-size: 90%; +} +*/ + + +/* SECTION 6: more reveal.js specific additions by @skypanther */ +ul, ol, div, p { + visibility: visible; + position: static; + width: auto; + height: auto; + display: block; + overflow: visible; + margin: auto; + text-align: left !important; +} +.reveal .slides { + position: static; + width: auto; + height: auto; + + left: auto; + top: auto; + margin-left: auto; + margin-top: auto; + padding: auto; + + overflow: visible; + display: block; + + text-align: center; + -webkit-perspective: none; + -moz-perspective: none; + -ms-perspective: none; + perspective: none; + + -webkit-perspective-origin: 50% 50%; /* there isn't a none/auto value but 50-50 is the default */ + -moz-perspective-origin: 50% 50%; + -ms-perspective-origin: 50% 50%; + perspective-origin: 50% 50%; +} +.reveal .slides>section, +.reveal .slides>section>section { + + visibility: visible !important; + position: static !important; + width: 90% !important; + height: auto !important; + display: block !important; + overflow: visible !important; + + left: 0% !important; + top: 0% !important; + margin-left: 0px !important; + margin-top: 0px !important; + padding: 20px 0px !important; + + opacity: 1 !important; + + -webkit-transform-style: flat !important; + -moz-transform-style: flat !important; + -ms-transform-style: flat !important; + transform-style: flat !important; + + -webkit-transform: none !important; + -moz-transform: none !important; + -ms-transform: none !important; + transform: none !important; +} +.reveal section { + page-break-after: always !important; + display: block !important; +} +.reveal section .fragment { + opacity: 1 !important; + visibility: visible !important; + + -webkit-transform: none !important; + -moz-transform: none !important; + -ms-transform: none !important; + transform: none !important; +} +.reveal section:last-of-type { + page-break-after: avoid !important; +} +.reveal section img { + display: block; + margin: 15px 0px; + background: rgba(255,255,255,1); + border: 1px solid #666; + box-shadow: none; +} \ No newline at end of file diff --git a/asm-talk/css/print/pdf.css b/asm-talk/css/print/pdf.css new file mode 100644 index 0000000..7b66ee5 --- /dev/null +++ b/asm-talk/css/print/pdf.css @@ -0,0 +1,190 @@ +/* Default Print Stylesheet Template + by Rob Glazebrook of CSSnewbie.com + Last Updated: June 4, 2008 + + Feel free (nay, compelled) to edit, append, and + manipulate this file as you see fit. */ + + +/* SECTION 1: Set default width, margin, float, and + background. This prevents elements from extending + beyond the edge of the printed page, and prevents + unnecessary background images from printing */ + +* { + -webkit-print-color-adjust: exact; +} + +body { + font-size: 18pt; + width: 297mm; + height: 229mm; + margin: 0 auto !important; + border: 0; + padding: 0; + float: none !important; + overflow: visible; +} + +html { + width: 100%; + height: 100%; + overflow: visible; +} + +@page { + size: letter landscape; + margin: 0; +} + +/* SECTION 2: Remove any elements not needed in print. + This would include navigation, ads, sidebars, etc. */ +.nestedarrow, +.controls, +.reveal .progress, +.reveal.overview, +.fork-reveal, +.share-reveal, +.state-background { + display: none !important; +} + +/* SECTION 3: Set body font face, size, and color. + Consider using a serif font for readability. */ +body, p, td, li, div { + font-size: 18pt; +} + +/* SECTION 4: Set heading font face, sizes, and color. + Differentiate your headings from your body text. + Perhaps use a large sans-serif for distinction. */ +h1,h2,h3,h4,h5,h6 { + text-shadow: 0 0 0 #000 !important; +} + +/* SECTION 5: Make hyperlinks more usable. + Ensure links are underlined, and consider appending + the URL to the end of the link for usability. */ +a:link, +a:visited { + font-weight: bold; + text-decoration: underline; +} + +.reveal pre code { + overflow: hidden !important; + font-family: monospace !important; +} + + +/* SECTION 6: more reveal.js specific additions by @skypanther */ +ul, ol, div, p { + visibility: visible; + position: static; + width: auto; + height: auto; + display: block; + overflow: visible; + margin: auto; +} +.reveal { + width: auto !important; + height: auto !important; + overflow: hidden !important; +} +.reveal .slides { + position: static; + width: 100%; + height: auto; + + left: auto; + top: auto; + margin: 0 !important; + padding: 0 !important; + + overflow: visible; + display: block; + + text-align: center; + + -webkit-perspective: none; + -moz-perspective: none; + -ms-perspective: none; + perspective: none; + + -webkit-perspective-origin: 50% 50%; /* there isn't a none/auto value but 50-50 is the default */ + -moz-perspective-origin: 50% 50%; + -ms-perspective-origin: 50% 50%; + perspective-origin: 50% 50%; +} +.reveal .slides section { + + page-break-after: always !important; + + visibility: visible !important; + position: relative !important; + width: 100% !important; + height: 229mm !important; + min-height: 229mm !important; + display: block !important; + overflow: hidden !important; + + left: 0 !important; + top: 0 !important; + margin: 0 !important; + padding: 2cm 2cm 0 2cm !important; + box-sizing: border-box !important; + + opacity: 1 !important; + + -webkit-transform-style: flat !important; + -moz-transform-style: flat !important; + -ms-transform-style: flat !important; + transform-style: flat !important; + + -webkit-transform: none !important; + -moz-transform: none !important; + -ms-transform: none !important; + transform: none !important; +} +.reveal section.stack { + margin: 0 !important; + padding: 0 !important; + page-break-after: avoid !important; + height: auto !important; + min-height: auto !important; +} +.reveal .absolute-element { + margin-left: 2.2cm; + margin-top: 1.8cm; +} +.reveal section .fragment { + opacity: 1 !important; + visibility: visible !important; + + -webkit-transform: none !important; + -moz-transform: none !important; + -ms-transform: none !important; + transform: none !important; +} +.reveal section .slide-background { + position: absolute; + top: 0; + left: 0; + width: 100%; + z-index: 0; +} +.reveal section>* { + position: relative; + z-index: 1; +} +.reveal img { + box-shadow: none; +} +.reveal .roll { + overflow: visible; + line-height: 1em; +} +.reveal small a { + font-size: 16pt !important; +} diff --git a/asm-talk/css/reveal.min.css b/asm-talk/css/reveal.min.css new file mode 100644 index 0000000..9fe9e40 --- /dev/null +++ b/asm-talk/css/reveal.min.css @@ -0,0 +1,7 @@ +@charset "UTF-8";/*! + * reveal.js + * http://lab.hakim.se/reveal-js + * MIT licensed + * + * Copyright (C) 2013 Hakim El Hattab, http://hakim.se + */ html,body,.reveal div,.reveal span,.reveal applet,.reveal object,.reveal iframe,.reveal h1,.reveal h2,.reveal h3,.reveal h4,.reveal h5,.reveal h6,.reveal p,.reveal blockquote,.reveal pre,.reveal a,.reveal abbr,.reveal acronym,.reveal address,.reveal big,.reveal cite,.reveal code,.reveal del,.reveal dfn,.reveal em,.reveal img,.reveal ins,.reveal kbd,.reveal q,.reveal s,.reveal samp,.reveal small,.reveal strike,.reveal strong,.reveal sub,.reveal sup,.reveal tt,.reveal var,.reveal b,.reveal u,.reveal i,.reveal center,.reveal dl,.reveal dt,.reveal dd,.reveal ol,.reveal ul,.reveal li,.reveal fieldset,.reveal form,.reveal label,.reveal legend,.reveal table,.reveal caption,.reveal tbody,.reveal tfoot,.reveal thead,.reveal tr,.reveal th,.reveal td,.reveal article,.reveal aside,.reveal canvas,.reveal details,.reveal embed,.reveal figure,.reveal figcaption,.reveal footer,.reveal header,.reveal hgroup,.reveal menu,.reveal nav,.reveal output,.reveal ruby,.reveal section,.reveal summary,.reveal time,.reveal mark,.reveal audio,video{margin:0;padding:0;border:0;font-size:100%;font:inherit;vertical-align:baseline}.reveal article,.reveal aside,.reveal details,.reveal figcaption,.reveal figure,.reveal footer,.reveal header,.reveal hgroup,.reveal menu,.reveal nav,.reveal section{display:block}html,body{width:100%;height:100%;overflow:hidden}body{position:relative;line-height:1}::selection{background:#FF5E99;color:#fff;text-shadow:none}.reveal h1,.reveal h2,.reveal h3,.reveal h4,.reveal h5,.reveal h6{-webkit-hyphens:auto;-moz-hyphens:auto;hyphens:auto;word-wrap:break-word}.reveal h1{font-size:3.77em}.reveal h2{font-size:2.11em}.reveal h3{font-size:1.55em}.reveal h4{font-size:1em}.reveal .slides section .fragment{opacity:0;-webkit-transition:all .2s ease;-moz-transition:all .2s ease;-ms-transition:all .2s ease;-o-transition:all .2s ease;transition:all .2s ease}.reveal .slides section .fragment.visible{opacity:1}.reveal .slides section .fragment.grow{opacity:1}.reveal .slides section .fragment.grow.visible{-webkit-transform:scale(1.3);-moz-transform:scale(1.3);-ms-transform:scale(1.3);-o-transform:scale(1.3);transform:scale(1.3)}.reveal .slides section .fragment.shrink{opacity:1}.reveal .slides section .fragment.shrink.visible{-webkit-transform:scale(0.7);-moz-transform:scale(0.7);-ms-transform:scale(0.7);-o-transform:scale(0.7);transform:scale(0.7)}.reveal .slides section .fragment.zoom-in{opacity:0;-webkit-transform:scale(0.1);-moz-transform:scale(0.1);-ms-transform:scale(0.1);-o-transform:scale(0.1);transform:scale(0.1)}.reveal .slides section .fragment.zoom-in.visible{opacity:1;-webkit-transform:scale(1);-moz-transform:scale(1);-ms-transform:scale(1);-o-transform:scale(1);transform:scale(1)}.reveal .slides section .fragment.roll-in{opacity:0;-webkit-transform:rotateX(90deg);-moz-transform:rotateX(90deg);-ms-transform:rotateX(90deg);-o-transform:rotateX(90deg);transform:rotateX(90deg)}.reveal .slides section .fragment.roll-in.visible{opacity:1;-webkit-transform:rotateX(0);-moz-transform:rotateX(0);-ms-transform:rotateX(0);-o-transform:rotateX(0);transform:rotateX(0)}.reveal .slides section .fragment.fade-out{opacity:1}.reveal .slides section .fragment.fade-out.visible{opacity:0}.reveal .slides section .fragment.semi-fade-out{opacity:1}.reveal .slides section .fragment.semi-fade-out.visible{opacity:.5}.reveal .slides section .fragment.highlight-red,.reveal .slides section .fragment.highlight-green,.reveal .slides section .fragment.highlight-blue{opacity:1}.reveal .slides section .fragment.highlight-red.visible{color:#ff2c2d}.reveal .slides section .fragment.highlight-green.visible{color:#17ff2e}.reveal .slides section .fragment.highlight-blue.visible{color:#1b91ff}.reveal:after{content:'';font-style:italic}.reveal img,.reveal video,.reveal iframe{max-width:95%;max-height:95%}.reveal a{position:relative}.reveal strong,.reveal b{font-weight:700}.reveal em,.reveal i{font-style:italic}.reveal ol,.reveal ul{display:inline-block;text-align:left;margin:0 0 0 1em}.reveal ol{list-style-type:decimal}.reveal ul{list-style-type:disc}.reveal ul ul{list-style-type:square}.reveal ul ul ul{list-style-type:circle}.reveal ul ul,.reveal ul ol,.reveal ol ol,.reveal ol ul{display:block;margin-left:40px}.reveal p{margin-bottom:10px;line-height:1.2em}.reveal q,.reveal blockquote{quotes:none}.reveal blockquote{display:block;position:relative;width:70%;margin:5px auto;padding:5px;font-style:italic;background:rgba(255,255,255,.05);box-shadow:0 0 2px rgba(0,0,0,.2)}.reveal blockquote p:first-child,.reveal blockquote p:last-child{display:inline-block}.reveal q{font-style:italic}.reveal pre{display:block;position:relative;width:100%;margin:15px auto;text-align:left;font-size:.55em;font-family:monospace;line-height:1.2em;word-wrap:break-word;box-shadow:0 0 6px rgba(0,0,0,.3)}.reveal code{font-family:monospace}.reveal pre code{padding:5px;overflow:auto;max-height:400px;word-wrap:normal}.reveal table th,.reveal table td{text-align:left;padding-right:.3em}.reveal table th{text-shadow:#fff 1px 1px 2px}.reveal sup{vertical-align:super}.reveal sub{vertical-align:sub}.reveal small{display:inline-block;font-size:.6em;line-height:1.2em;vertical-align:top}.reveal small *{vertical-align:top}.reveal .controls{display:none;position:fixed;width:110px;height:110px;z-index:30;right:10px;bottom:10px}.reveal .controls div{position:absolute;opacity:.05;width:0;height:0;border:12px solid transparent;-moz-transform:scale(.9999);-webkit-transition:all .2s ease;-moz-transition:all .2s ease;-ms-transition:all .2s ease;-o-transition:all .2s ease;transition:all .2s ease}.reveal .controls div.enabled{opacity:.7;cursor:pointer}.reveal .controls div.enabled:active{margin-top:1px}.reveal .controls div.navigate-left{top:42px;border-right-width:22px;border-right-color:#eee}.reveal .controls div.navigate-left.fragmented{opacity:.3}.reveal .controls div.navigate-right{left:74px;top:42px;border-left-width:22px;border-left-color:#eee}.reveal .controls div.navigate-right.fragmented{opacity:.3}.reveal .controls div.navigate-up{left:42px;border-bottom-width:22px;border-bottom-color:#eee}.reveal .controls div.navigate-up.fragmented{opacity:.3}.reveal .controls div.navigate-down{left:42px;top:74px;border-top-width:22px;border-top-color:#eee}.reveal .controls div.navigate-down.fragmented{opacity:.3}.reveal .progress{position:fixed;display:none;height:3px;width:100%;bottom:0;left:0;z-index:10}.reveal .progress:after{content:'';display:'block';position:absolute;height:20px;width:100%;top:-20px}.reveal .progress span{display:block;height:100%;width:0;-webkit-transition:width 800ms cubic-bezier(0.26,.86,.44,.985);-moz-transition:width 800ms cubic-bezier(0.26,.86,.44,.985);-ms-transition:width 800ms cubic-bezier(0.26,.86,.44,.985);-o-transition:width 800ms cubic-bezier(0.26,.86,.44,.985);transition:width 800ms cubic-bezier(0.26,.86,.44,.985)}.reveal .roll{display:inline-block;line-height:1.2;overflow:hidden;vertical-align:top;-webkit-perspective:400px;-moz-perspective:400px;-ms-perspective:400px;perspective:400px;-webkit-perspective-origin:50% 50%;-moz-perspective-origin:50% 50%;-ms-perspective-origin:50% 50%;perspective-origin:50% 50%}.reveal .roll:hover{background:0;text-shadow:none}.reveal .roll span{display:block;position:relative;padding:0 2px;pointer-events:none;-webkit-transition:all 400ms ease;-moz-transition:all 400ms ease;-ms-transition:all 400ms ease;transition:all 400ms ease;-webkit-transform-origin:50% 0;-moz-transform-origin:50% 0;-ms-transform-origin:50% 0;transform-origin:50% 0;-webkit-transform-style:preserve-3d;-moz-transform-style:preserve-3d;-ms-transform-style:preserve-3d;transform-style:preserve-3d;-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden;backface-visibility:hidden}.reveal .roll:hover span{background:rgba(0,0,0,.5);-webkit-transform:translate3d(0px,0,-45px) rotateX(90deg);-moz-transform:translate3d(0px,0,-45px) rotateX(90deg);-ms-transform:translate3d(0px,0,-45px) rotateX(90deg);transform:translate3d(0px,0,-45px) rotateX(90deg)}.reveal .roll span:after{content:attr(data-title);display:block;position:absolute;left:0;top:0;padding:0 2px;-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform-origin:50% 0;-moz-transform-origin:50% 0;-ms-transform-origin:50% 0;transform-origin:50% 0;-webkit-transform:translate3d(0px,110%,0) rotateX(-90deg);-moz-transform:translate3d(0px,110%,0) rotateX(-90deg);-ms-transform:translate3d(0px,110%,0) rotateX(-90deg);transform:translate3d(0px,110%,0) rotateX(-90deg)}.reveal{position:relative;width:100%;height:100%;-ms-touch-action:none}.reveal .slides{position:absolute;width:100%;height:100%;left:50%;top:50%;overflow:visible;z-index:1;text-align:center;-webkit-transition:-webkit-perspective .4s ease;-moz-transition:-moz-perspective .4s ease;-ms-transition:-ms-perspective .4s ease;-o-transition:-o-perspective .4s ease;transition:perspective .4s ease;-webkit-perspective:600px;-moz-perspective:600px;-ms-perspective:600px;perspective:600px;-webkit-perspective-origin:0 -100px;-moz-perspective-origin:0 -100px;-ms-perspective-origin:0 -100px;perspective-origin:0 -100px}.reveal .slides>section,.reveal .slides>section>section{display:none;position:absolute;width:100%;padding:20px 0;z-index:10;line-height:1.2em;font-weight:400;-webkit-transform-style:preserve-3d;-moz-transform-style:preserve-3d;-ms-transform-style:preserve-3d;transform-style:preserve-3d;-webkit-transition:-webkit-transform-origin 800ms cubic-bezier(0.26,.86,.44,.985),-webkit-transform 800ms cubic-bezier(0.26,.86,.44,.985),visibility 800ms cubic-bezier(0.26,.86,.44,.985),opacity 800ms cubic-bezier(0.26,.86,.44,.985);-moz-transition:-moz-transform-origin 800ms cubic-bezier(0.26,.86,.44,.985),-moz-transform 800ms cubic-bezier(0.26,.86,.44,.985),visibility 800ms cubic-bezier(0.26,.86,.44,.985),opacity 800ms cubic-bezier(0.26,.86,.44,.985);-ms-transition:-ms-transform-origin 800ms cubic-bezier(0.26,.86,.44,.985),-ms-transform 800ms cubic-bezier(0.26,.86,.44,.985),visibility 800ms cubic-bezier(0.26,.86,.44,.985),opacity 800ms cubic-bezier(0.26,.86,.44,.985);-o-transition:-o-transform-origin 800ms cubic-bezier(0.26,.86,.44,.985),-o-transform 800ms cubic-bezier(0.26,.86,.44,.985),visibility 800ms cubic-bezier(0.26,.86,.44,.985),opacity 800ms cubic-bezier(0.26,.86,.44,.985);transition:transform-origin 800ms cubic-bezier(0.26,.86,.44,.985),transform 800ms cubic-bezier(0.26,.86,.44,.985),visibility 800ms cubic-bezier(0.26,.86,.44,.985),opacity 800ms cubic-bezier(0.26,.86,.44,.985)}.reveal[data-transition-speed=fast] .slides section{-webkit-transition-duration:400ms;-moz-transition-duration:400ms;-ms-transition-duration:400ms;transition-duration:400ms}.reveal[data-transition-speed=slow] .slides section{-webkit-transition-duration:1200ms;-moz-transition-duration:1200ms;-ms-transition-duration:1200ms;transition-duration:1200ms}.reveal .slides section[data-transition-speed=fast]{-webkit-transition-duration:400ms;-moz-transition-duration:400ms;-ms-transition-duration:400ms;transition-duration:400ms}.reveal .slides section[data-transition-speed=slow]{-webkit-transition-duration:1200ms;-moz-transition-duration:1200ms;-ms-transition-duration:1200ms;transition-duration:1200ms}.reveal .slides>section{left:-50%;top:-50%}.reveal .slides>section.stack{padding-top:0;padding-bottom:0}.reveal .slides>section.present,.reveal .slides>section>section.present{display:block;z-index:11;opacity:1}.reveal.center,.reveal.center .slides,.reveal.center .slides section{min-height:auto!important}.reveal .slides>section[data-transition=default].past,.reveal .slides>section.past{display:block;opacity:0;-webkit-transform:translate3d(-100%,0,0) rotateY(-90deg) translate3d(-100%,0,0);-moz-transform:translate3d(-100%,0,0) rotateY(-90deg) translate3d(-100%,0,0);-ms-transform:translate3d(-100%,0,0) rotateY(-90deg) translate3d(-100%,0,0);transform:translate3d(-100%,0,0) rotateY(-90deg) translate3d(-100%,0,0)}.reveal .slides>section[data-transition=default].future,.reveal .slides>section.future{display:block;opacity:0;-webkit-transform:translate3d(100%,0,0) rotateY(90deg) translate3d(100%,0,0);-moz-transform:translate3d(100%,0,0) rotateY(90deg) translate3d(100%,0,0);-ms-transform:translate3d(100%,0,0) rotateY(90deg) translate3d(100%,0,0);transform:translate3d(100%,0,0) rotateY(90deg) translate3d(100%,0,0)}.reveal .slides>section>section[data-transition=default].past,.reveal .slides>section>section.past{display:block;opacity:0;-webkit-transform:translate3d(0,-300px,0) rotateX(70deg) translate3d(0,-300px,0);-moz-transform:translate3d(0,-300px,0) rotateX(70deg) translate3d(0,-300px,0);-ms-transform:translate3d(0,-300px,0) rotateX(70deg) translate3d(0,-300px,0);transform:translate3d(0,-300px,0) rotateX(70deg) translate3d(0,-300px,0)}.reveal .slides>section>section[data-transition=default].future,.reveal .slides>section>section.future{display:block;opacity:0;-webkit-transform:translate3d(0,300px,0) rotateX(-70deg) translate3d(0,300px,0);-moz-transform:translate3d(0,300px,0) rotateX(-70deg) translate3d(0,300px,0);-ms-transform:translate3d(0,300px,0) rotateX(-70deg) translate3d(0,300px,0);transform:translate3d(0,300px,0) rotateX(-70deg) translate3d(0,300px,0)}.reveal .slides>section[data-transition=concave].past,.reveal.concave .slides>section.past{-webkit-transform:translate3d(-100%,0,0) rotateY(90deg) translate3d(-100%,0,0);-moz-transform:translate3d(-100%,0,0) rotateY(90deg) translate3d(-100%,0,0);-ms-transform:translate3d(-100%,0,0) rotateY(90deg) translate3d(-100%,0,0);transform:translate3d(-100%,0,0) rotateY(90deg) translate3d(-100%,0,0)}.reveal .slides>section[data-transition=concave].future,.reveal.concave .slides>section.future{-webkit-transform:translate3d(100%,0,0) rotateY(-90deg) translate3d(100%,0,0);-moz-transform:translate3d(100%,0,0) rotateY(-90deg) translate3d(100%,0,0);-ms-transform:translate3d(100%,0,0) rotateY(-90deg) translate3d(100%,0,0);transform:translate3d(100%,0,0) rotateY(-90deg) translate3d(100%,0,0)}.reveal .slides>section>section[data-transition=concave].past,.reveal.concave .slides>section>section.past{-webkit-transform:translate3d(0,-80%,0) rotateX(-70deg) translate3d(0,-80%,0);-moz-transform:translate3d(0,-80%,0) rotateX(-70deg) translate3d(0,-80%,0);-ms-transform:translate3d(0,-80%,0) rotateX(-70deg) translate3d(0,-80%,0);transform:translate3d(0,-80%,0) rotateX(-70deg) translate3d(0,-80%,0)}.reveal .slides>section>section[data-transition=concave].future,.reveal.concave .slides>section>section.future{-webkit-transform:translate3d(0,80%,0) rotateX(70deg) translate3d(0,80%,0);-moz-transform:translate3d(0,80%,0) rotateX(70deg) translate3d(0,80%,0);-ms-transform:translate3d(0,80%,0) rotateX(70deg) translate3d(0,80%,0);transform:translate3d(0,80%,0) rotateX(70deg) translate3d(0,80%,0)}.reveal .slides>section[data-transition=zoom].past,.reveal.zoom .slides>section.past{opacity:0;visibility:hidden;-webkit-transform:scale(16);-moz-transform:scale(16);-ms-transform:scale(16);-o-transform:scale(16);transform:scale(16)}.reveal .slides>section[data-transition=zoom].future,.reveal.zoom .slides>section.future{opacity:0;visibility:hidden;-webkit-transform:scale(0.2);-moz-transform:scale(0.2);-ms-transform:scale(0.2);-o-transform:scale(0.2);transform:scale(0.2)}.reveal .slides>section>section[data-transition=zoom].past,.reveal.zoom .slides>section>section.past{-webkit-transform:translate(0,-150%);-moz-transform:translate(0,-150%);-ms-transform:translate(0,-150%);-o-transform:translate(0,-150%);transform:translate(0,-150%)}.reveal .slides>section>section[data-transition=zoom].future,.reveal.zoom .slides>section>section.future{-webkit-transform:translate(0,150%);-moz-transform:translate(0,150%);-ms-transform:translate(0,150%);-o-transform:translate(0,150%);transform:translate(0,150%)}.reveal.linear section{-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden;-ms-backface-visibility:hidden;backface-visibility:hidden}.reveal .slides>section[data-transition=linear].past,.reveal.linear .slides>section.past{-webkit-transform:translate(-150%,0);-moz-transform:translate(-150%,0);-ms-transform:translate(-150%,0);-o-transform:translate(-150%,0);transform:translate(-150%,0)}.reveal .slides>section[data-transition=linear].future,.reveal.linear .slides>section.future{-webkit-transform:translate(150%,0);-moz-transform:translate(150%,0);-ms-transform:translate(150%,0);-o-transform:translate(150%,0);transform:translate(150%,0)}.reveal .slides>section>section[data-transition=linear].past,.reveal.linear .slides>section>section.past{-webkit-transform:translate(0,-150%);-moz-transform:translate(0,-150%);-ms-transform:translate(0,-150%);-o-transform:translate(0,-150%);transform:translate(0,-150%)}.reveal .slides>section>section[data-transition=linear].future,.reveal.linear .slides>section>section.future{-webkit-transform:translate(0,150%);-moz-transform:translate(0,150%);-ms-transform:translate(0,150%);-o-transform:translate(0,150%);transform:translate(0,150%)}.reveal.cube .slides{-webkit-perspective:1300px;-moz-perspective:1300px;-ms-perspective:1300px;perspective:1300px}.reveal.cube .slides section{padding:30px;min-height:700px;-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden;-ms-backface-visibility:hidden;backface-visibility:hidden;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.reveal.center.cube .slides section{min-height:auto}.reveal.cube .slides section:not(.stack):before{content:'';position:absolute;display:block;width:100%;height:100%;left:0;top:0;background:rgba(0,0,0,.1);border-radius:4px;-webkit-transform:translateZ(-20px);-moz-transform:translateZ(-20px);-ms-transform:translateZ(-20px);-o-transform:translateZ(-20px);transform:translateZ(-20px)}.reveal.cube .slides section:not(.stack):after{content:'';position:absolute;display:block;width:100%;height:30px;left:5%;bottom:0;background:0;z-index:1;border-radius:4px;box-shadow:0 95px 25px rgba(0,0,0,.2);-webkit-transform:translateZ(-90px) rotateX(65deg);-moz-transform:translateZ(-90px) rotateX(65deg);-ms-transform:translateZ(-90px) rotateX(65deg);-o-transform:translateZ(-90px) rotateX(65deg);transform:translateZ(-90px) rotateX(65deg)}.reveal.cube .slides>section.stack{padding:0;background:0}.reveal.cube .slides>section.past{-webkit-transform-origin:100% 0;-moz-transform-origin:100% 0;-ms-transform-origin:100% 0;transform-origin:100% 0;-webkit-transform:translate3d(-100%,0,0) rotateY(-90deg);-moz-transform:translate3d(-100%,0,0) rotateY(-90deg);-ms-transform:translate3d(-100%,0,0) rotateY(-90deg);transform:translate3d(-100%,0,0) rotateY(-90deg)}.reveal.cube .slides>section.future{-webkit-transform-origin:0 0;-moz-transform-origin:0 0;-ms-transform-origin:0 0;transform-origin:0 0;-webkit-transform:translate3d(100%,0,0) rotateY(90deg);-moz-transform:translate3d(100%,0,0) rotateY(90deg);-ms-transform:translate3d(100%,0,0) rotateY(90deg);transform:translate3d(100%,0,0) rotateY(90deg)}.reveal.cube .slides>section>section.past{-webkit-transform-origin:0 100%;-moz-transform-origin:0 100%;-ms-transform-origin:0 100%;transform-origin:0 100%;-webkit-transform:translate3d(0,-100%,0) rotateX(90deg);-moz-transform:translate3d(0,-100%,0) rotateX(90deg);-ms-transform:translate3d(0,-100%,0) rotateX(90deg);transform:translate3d(0,-100%,0) rotateX(90deg)}.reveal.cube .slides>section>section.future{-webkit-transform-origin:0 0;-moz-transform-origin:0 0;-ms-transform-origin:0 0;transform-origin:0 0;-webkit-transform:translate3d(0,100%,0) rotateX(-90deg);-moz-transform:translate3d(0,100%,0) rotateX(-90deg);-ms-transform:translate3d(0,100%,0) rotateX(-90deg);transform:translate3d(0,100%,0) rotateX(-90deg)}.reveal.page .slides{-webkit-perspective-origin:0 50%;-moz-perspective-origin:0 50%;-ms-perspective-origin:0 50%;perspective-origin:0 50%;-webkit-perspective:3000px;-moz-perspective:3000px;-ms-perspective:3000px;perspective:3000px}.reveal.page .slides section{padding:30px;min-height:700px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.reveal.page .slides section.past{z-index:12}.reveal.page .slides section:not(.stack):before{content:'';position:absolute;display:block;width:100%;height:100%;left:0;top:0;background:rgba(0,0,0,.1);-webkit-transform:translateZ(-20px);-moz-transform:translateZ(-20px);-ms-transform:translateZ(-20px);-o-transform:translateZ(-20px);transform:translateZ(-20px)}.reveal.page .slides section:not(.stack):after{content:'';position:absolute;display:block;width:100%;height:30px;left:5%;bottom:0;background:0;z-index:1;border-radius:4px;box-shadow:0 95px 25px rgba(0,0,0,.2);-webkit-transform:translateZ(-90px) rotateX(65deg)}.reveal.page .slides>section.stack{padding:0;background:0}.reveal.page .slides>section.past{-webkit-transform-origin:0 0;-moz-transform-origin:0 0;-ms-transform-origin:0 0;transform-origin:0 0;-webkit-transform:translate3d(-40%,0,0) rotateY(-80deg);-moz-transform:translate3d(-40%,0,0) rotateY(-80deg);-ms-transform:translate3d(-40%,0,0) rotateY(-80deg);transform:translate3d(-40%,0,0) rotateY(-80deg)}.reveal.page .slides>section.future{-webkit-transform-origin:100% 0;-moz-transform-origin:100% 0;-ms-transform-origin:100% 0;transform-origin:100% 0;-webkit-transform:translate3d(0,0,0);-moz-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.reveal.page .slides>section>section.past{-webkit-transform-origin:0 0;-moz-transform-origin:0 0;-ms-transform-origin:0 0;transform-origin:0 0;-webkit-transform:translate3d(0,-40%,0) rotateX(80deg);-moz-transform:translate3d(0,-40%,0) rotateX(80deg);-ms-transform:translate3d(0,-40%,0) rotateX(80deg);transform:translate3d(0,-40%,0) rotateX(80deg)}.reveal.page .slides>section>section.future{-webkit-transform-origin:0 100%;-moz-transform-origin:0 100%;-ms-transform-origin:0 100%;transform-origin:0 100%;-webkit-transform:translate3d(0,0,0);-moz-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.reveal .slides section[data-transition=fade],.reveal.fade .slides section,.reveal.fade .slides>section>section{-webkit-transform:none;-moz-transform:none;-ms-transform:none;-o-transform:none;transform:none;-webkit-transition:opacity .5s;-moz-transition:opacity .5s;-ms-transition:opacity .5s;-o-transition:opacity .5s;transition:opacity .5s}.reveal.fade.overview .slides section,.reveal.fade.overview .slides>section>section,.reveal.fade.exit-overview .slides section,.reveal.fade.exit-overview .slides>section>section{-webkit-transition:none;-moz-transition:none;-ms-transition:none;-o-transition:none;transition:none}.reveal .slides section[data-transition=none],.reveal.none .slides section{-webkit-transform:none;-moz-transform:none;-ms-transform:none;-o-transform:none;transform:none;-webkit-transition:none;-moz-transition:none;-ms-transition:none;-o-transition:none;transition:none}.reveal.overview .slides{-webkit-perspective-origin:0 0;-moz-perspective-origin:0 0;-ms-perspective-origin:0 0;perspective-origin:0 0;-webkit-perspective:700px;-moz-perspective:700px;-ms-perspective:700px;perspective:700px}.reveal.overview .slides section{height:600px;overflow:hidden;opacity:1!important;visibility:visible!important;cursor:pointer;background:rgba(0,0,0,.1)}.reveal.overview .slides section .fragment{opacity:1}.reveal.overview .slides section:after,.reveal.overview .slides section:before{display:none!important}.reveal.overview .slides section>section{opacity:1;cursor:pointer}.reveal.overview .slides section:hover{background:rgba(0,0,0,.3)}.reveal.overview .slides section.present{background:rgba(0,0,0,.3)}.reveal.overview .slides>section.stack{padding:0;background:0;overflow:visible}.reveal .pause-overlay{position:absolute;top:0;left:0;width:100%;height:100%;background:#000;visibility:hidden;opacity:0;z-index:100;-webkit-transition:all 1s ease;-moz-transition:all 1s ease;-ms-transition:all 1s ease;-o-transition:all 1s ease;transition:all 1s ease}.reveal.paused .pause-overlay{visibility:visible;opacity:1}.no-transforms{overflow-y:auto}.no-transforms .reveal .slides{position:relative;width:80%;height:auto!important;top:0;left:50%;margin:0;text-align:center}.no-transforms .reveal .controls,.no-transforms .reveal .progress{display:none!important}.no-transforms .reveal .slides section{display:block!important;opacity:1!important;position:relative!important;height:auto;min-height:auto;top:0;left:-50%;margin:70px 0;-webkit-transform:none;-moz-transform:none;-ms-transform:none;-o-transform:none;transform:none}.no-transforms .reveal .slides section section{left:0}.reveal .no-transition,.reveal .no-transition *{-webkit-transition:none!important;-moz-transition:none!important;-ms-transition:none!important;-o-transition:none!important;transition:none!important}.reveal .state-background{position:absolute;width:100%;height:100%;background:rgba(0,0,0,0);-webkit-transition:background 800ms ease;-moz-transition:background 800ms ease;-ms-transition:background 800ms ease;-o-transition:background 800ms ease;transition:background 800ms ease}.alert .reveal .state-background{background:rgba(200,50,30,.6)}.soothe .reveal .state-background{background:rgba(50,200,90,.4)}.blackout .reveal .state-background{background:rgba(0,0,0,.6)}.whiteout .reveal .state-background{background:rgba(255,255,255,.6)}.cobalt .reveal .state-background{background:rgba(22,152,213,.6)}.mint .reveal .state-background{background:rgba(22,213,75,.6)}.submerge .reveal .state-background{background:rgba(12,25,77,.6)}.lila .reveal .state-background{background:rgba(180,50,140,.6)}.sunset .reveal .state-background{background:rgba(255,122,0,.6)}.reveal>.backgrounds{position:absolute;width:100%;height:100%}.reveal .slide-background{position:absolute;width:100%;height:100%;opacity:0;visibility:hidden;background-color:rgba(0,0,0,0);background-position:50% 50%;background-repeat:no-repeat;background-size:cover;-webkit-transition:all 600ms cubic-bezier(0.26,.86,.44,.985);-moz-transition:all 600ms cubic-bezier(0.26,.86,.44,.985);-ms-transition:all 600ms cubic-bezier(0.26,.86,.44,.985);-o-transition:all 600ms cubic-bezier(0.26,.86,.44,.985);transition:all 600ms cubic-bezier(0.26,.86,.44,.985)}.reveal .slide-background.present{opacity:1;visibility:visible}.print-pdf .reveal .slide-background{opacity:1!important;visibility:visible!important}.reveal[data-background-transition=slide]>.backgrounds .slide-background,.reveal>.backgrounds .slide-background[data-background-transition=slide]{opacity:1;-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden;-ms-backface-visibility:hidden;backface-visibility:hidden;-webkit-transition-duration:800ms;-moz-transition-duration:800ms;-ms-transition-duration:800ms;-o-transition-duration:800ms;transition-duration:800ms}.reveal[data-background-transition=slide]>.backgrounds .slide-background.past,.reveal>.backgrounds .slide-background.past[data-background-transition=slide]{-webkit-transform:translate(-100%,0);-moz-transform:translate(-100%,0);-ms-transform:translate(-100%,0);-o-transform:translate(-100%,0);transform:translate(-100%,0)}.reveal[data-background-transition=slide]>.backgrounds .slide-background.future,.reveal>.backgrounds .slide-background.future[data-background-transition=slide]{-webkit-transform:translate(100%,0);-moz-transform:translate(100%,0);-ms-transform:translate(100%,0);-o-transform:translate(100%,0);transform:translate(100%,0)}.reveal[data-background-transition=slide]>.backgrounds .slide-background>.slide-background.past,.reveal>.backgrounds .slide-background>.slide-background.past[data-background-transition=slide]{-webkit-transform:translate(0,-100%);-moz-transform:translate(0,-100%);-ms-transform:translate(0,-100%);-o-transform:translate(0,-100%);transform:translate(0,-100%)}.reveal[data-background-transition=slide]>.backgrounds .slide-background>.slide-background.future,.reveal>.backgrounds .slide-background>.slide-background.future[data-background-transition=slide]{-webkit-transform:translate(0,100%);-moz-transform:translate(0,100%);-ms-transform:translate(0,100%);-o-transform:translate(0,100%);transform:translate(0,100%)}.reveal[data-transition-speed=fast]>.backgrounds .slide-background{-webkit-transition-duration:400ms;-moz-transition-duration:400ms;-ms-transition-duration:400ms;transition-duration:400ms}.reveal[data-transition-speed=slow]>.backgrounds .slide-background{-webkit-transition-duration:1200ms;-moz-transition-duration:1200ms;-ms-transition-duration:1200ms;transition-duration:1200ms}.reveal.rtl .slides,.reveal.rtl .slides h1,.reveal.rtl .slides h2,.reveal.rtl .slides h3,.reveal.rtl .slides h4,.reveal.rtl .slides h5,.reveal.rtl .slides h6{direction:rtl;font-family:sans-serif}.reveal.rtl pre,.reveal.rtl code{direction:ltr}.reveal.rtl ol,.reveal.rtl ul{text-align:right}.reveal.rtl .progress span{float:right}.reveal .preview-link-overlay{position:absolute;top:0;left:0;width:100%;height:100%;z-index:1000;background:rgba(0,0,0,.9);opacity:0;visibility:hidden;-webkit-transition:all .3s ease;-moz-transition:all .3s ease;-ms-transition:all .3s ease;transition:all .3s ease}.reveal .preview-link-overlay.visible{opacity:1;visibility:visible}.reveal .preview-link-overlay .spinner{position:absolute;display:block;top:50%;left:50%;width:32px;height:32px;margin:-16px 0 0 -16px;z-index:10;background-image:url(data:image/gif;base64,R0lGODlhIAAgAPMAAJmZmf%2F%2F%2F6%2Bvr8nJybW1tcDAwOjo6Nvb26ioqKOjo7Ozs%2FLy8vz8%2FAAAAAAAAAAAACH%2FC05FVFNDQVBFMi4wAwEAAAAh%2FhpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh%2BQQJCgAAACwAAAAAIAAgAAAE5xDISWlhperN52JLhSSdRgwVo1ICQZRUsiwHpTJT4iowNS8vyW2icCF6k8HMMBkCEDskxTBDAZwuAkkqIfxIQyhBQBFvAQSDITM5VDW6XNE4KagNh6Bgwe60smQUB3d4Rz1ZBApnFASDd0hihh12BkE9kjAJVlycXIg7CQIFA6SlnJ87paqbSKiKoqusnbMdmDC2tXQlkUhziYtyWTxIfy6BE8WJt5YJvpJivxNaGmLHT0VnOgSYf0dZXS7APdpB309RnHOG5gDqXGLDaC457D1zZ%2FV%2FnmOM82XiHRLYKhKP1oZmADdEAAAh%2BQQJCgAAACwAAAAAIAAgAAAE6hDISWlZpOrNp1lGNRSdRpDUolIGw5RUYhhHukqFu8DsrEyqnWThGvAmhVlteBvojpTDDBUEIFwMFBRAmBkSgOrBFZogCASwBDEY%2FCZSg7GSE0gSCjQBMVG023xWBhklAnoEdhQEfyNqMIcKjhRsjEdnezB%2BA4k8gTwJhFuiW4dokXiloUepBAp5qaKpp6%2BHo7aWW54wl7obvEe0kRuoplCGepwSx2jJvqHEmGt6whJpGpfJCHmOoNHKaHx61WiSR92E4lbFoq%2BB6QDtuetcaBPnW6%2BO7wDHpIiK9SaVK5GgV543tzjgGcghAgAh%2BQQJCgAAACwAAAAAIAAgAAAE7hDISSkxpOrN5zFHNWRdhSiVoVLHspRUMoyUakyEe8PTPCATW9A14E0UvuAKMNAZKYUZCiBMuBakSQKG8G2FzUWox2AUtAQFcBKlVQoLgQReZhQlCIJesQXI5B0CBnUMOxMCenoCfTCEWBsJColTMANldx15BGs8B5wlCZ9Po6OJkwmRpnqkqnuSrayqfKmqpLajoiW5HJq7FL1Gr2mMMcKUMIiJgIemy7xZtJsTmsM4xHiKv5KMCXqfyUCJEonXPN2rAOIAmsfB3uPoAK%2B%2BG%2Bw48edZPK%2BM6hLJpQg484enXIdQFSS1u6UhksENEQAAIfkECQoAAAAsAAAAACAAIAAABOcQyEmpGKLqzWcZRVUQnZYg1aBSh2GUVEIQ2aQOE%2BG%2BcD4ntpWkZQj1JIiZIogDFFyHI0UxQwFugMSOFIPJftfVAEoZLBbcLEFhlQiqGp1Vd140AUklUN3eCA51C1EWMzMCezCBBmkxVIVHBWd3HHl9JQOIJSdSnJ0TDKChCwUJjoWMPaGqDKannasMo6WnM562R5YluZRwur0wpgqZE7NKUm%2BFNRPIhjBJxKZteWuIBMN4zRMIVIhffcgojwCF117i4nlLnY5ztRLsnOk%2BaV%2BoJY7V7m76PdkS4trKcdg0Zc0tTcKkRAAAIfkECQoAAAAsAAAAACAAIAAABO4QyEkpKqjqzScpRaVkXZWQEximw1BSCUEIlDohrft6cpKCk5xid5MNJTaAIkekKGQkWyKHkvhKsR7ARmitkAYDYRIbUQRQjWBwJRzChi9CRlBcY1UN4g0%2FVNB0AlcvcAYHRyZPdEQFYV8ccwR5HWxEJ02YmRMLnJ1xCYp0Y5idpQuhopmmC2KgojKasUQDk5BNAwwMOh2RtRq5uQuPZKGIJQIGwAwGf6I0JXMpC8C7kXWDBINFMxS4DKMAWVWAGYsAdNqW5uaRxkSKJOZKaU3tPOBZ4DuK2LATgJhkPJMgTwKCdFjyPHEnKxFCDhEAACH5BAkKAAAALAAAAAAgACAAAATzEMhJaVKp6s2nIkolIJ2WkBShpkVRWqqQrhLSEu9MZJKK9y1ZrqYK9WiClmvoUaF8gIQSNeF1Er4MNFn4SRSDARWroAIETg1iVwuHjYB1kYc1mwruwXKC9gmsJXliGxc%2BXiUCby9ydh1sOSdMkpMTBpaXBzsfhoc5l58Gm5yToAaZhaOUqjkDgCWNHAULCwOLaTmzswadEqggQwgHuQsHIoZCHQMMQgQGubVEcxOPFAcMDAYUA85eWARmfSRQCdcMe0zeP1AAygwLlJtPNAAL19DARdPzBOWSm1brJBi45soRAWQAAkrQIykShQ9wVhHCwCQCACH5BAkKAAAALAAAAAAgACAAAATrEMhJaVKp6s2nIkqFZF2VIBWhUsJaTokqUCoBq%2BE71SRQeyqUToLA7VxF0JDyIQh%2FMVVPMt1ECZlfcjZJ9mIKoaTl1MRIl5o4CUKXOwmyrCInCKqcWtvadL2SYhyASyNDJ0uIiRMDjI0Fd30%2FiI2UA5GSS5UDj2l6NoqgOgN4gksEBgYFf0FDqKgHnyZ9OX8HrgYHdHpcHQULXAS2qKpENRg7eAMLC7kTBaixUYFkKAzWAAnLC7FLVxLWDBLKCwaKTULgEwbLA4hJtOkSBNqITT3xEgfLpBtzE%2FjiuL04RGEBgwWhShRgQExHBAAh%2BQQJCgAAACwAAAAAIAAgAAAE7xDISWlSqerNpyJKhWRdlSAVoVLCWk6JKlAqAavhO9UkUHsqlE6CwO1cRdCQ8iEIfzFVTzLdRAmZX3I2SfZiCqGk5dTESJeaOAlClzsJsqwiJwiqnFrb2nS9kmIcgEsjQydLiIlHehhpejaIjzh9eomSjZR%2BipslWIRLAgMDOR2DOqKogTB9pCUJBagDBXR6XB0EBkIIsaRsGGMMAxoDBgYHTKJiUYEGDAzHC9EACcUGkIgFzgwZ0QsSBcXHiQvOwgDdEwfFs0sDzt4S6BK4xYjkDOzn0unFeBzOBijIm1Dgmg5YFQwsCMjp1oJ8LyIAACH5BAkKAAAALAAAAAAgACAAAATwEMhJaVKp6s2nIkqFZF2VIBWhUsJaTokqUCoBq%2BE71SRQeyqUToLA7VxF0JDyIQh%2FMVVPMt1ECZlfcjZJ9mIKoaTl1MRIl5o4CUKXOwmyrCInCKqcWtvadL2SYhyASyNDJ0uIiUd6GGl6NoiPOH16iZKNlH6KmyWFOggHhEEvAwwMA0N9GBsEC6amhnVcEwavDAazGwIDaH1ipaYLBUTCGgQDA8NdHz0FpqgTBwsLqAbWAAnIA4FWKdMLGdYGEgraigbT0OITBcg5QwPT4xLrROZL6AuQAPUS7bxLpoWidY0JtxLHKhwwMJBTHgPKdEQAACH5BAkKAAAALAAAAAAgACAAAATrEMhJaVKp6s2nIkqFZF2VIBWhUsJaTokqUCoBq%2BE71SRQeyqUToLA7VxF0JDyIQh%2FMVVPMt1ECZlfcjZJ9mIKoaTl1MRIl5o4CUKXOwmyrCInCKqcWtvadL2SYhyASyNDJ0uIiUd6GAULDJCRiXo1CpGXDJOUjY%2BYip9DhToJA4RBLwMLCwVDfRgbBAaqqoZ1XBMHswsHtxtFaH1iqaoGNgAIxRpbFAgfPQSqpbgGBqUD1wBXeCYp1AYZ19JJOYgH1KwA4UBvQwXUBxPqVD9L3sbp2BNk2xvvFPJd%2BMFCN6HAAIKgNggY0KtEBAAh%2BQQJCgAAACwAAAAAIAAgAAAE6BDISWlSqerNpyJKhWRdlSAVoVLCWk6JKlAqAavhO9UkUHsqlE6CwO1cRdCQ8iEIfzFVTzLdRAmZX3I2SfYIDMaAFdTESJeaEDAIMxYFqrOUaNW4E4ObYcCXaiBVEgULe0NJaxxtYksjh2NLkZISgDgJhHthkpU4mW6blRiYmZOlh4JWkDqILwUGBnE6TYEbCgevr0N1gH4At7gHiRpFaLNrrq8HNgAJA70AWxQIH1%2BvsYMDAzZQPC9VCNkDWUhGkuE5PxJNwiUK4UfLzOlD4WvzAHaoG9nxPi5d%2BjYUqfAhhykOFwJWiAAAIfkECQoAAAAsAAAAACAAIAAABPAQyElpUqnqzaciSoVkXVUMFaFSwlpOCcMYlErAavhOMnNLNo8KsZsMZItJEIDIFSkLGQoQTNhIsFehRww2CQLKF0tYGKYSg%2BygsZIuNqJksKgbfgIGepNo2cIUB3V1B3IvNiBYNQaDSTtfhhx0CwVPI0UJe0%2Bbm4g5VgcGoqOcnjmjqDSdnhgEoamcsZuXO1aWQy8KAwOAuTYYGwi7w5h%2BKr0SJ8MFihpNbx%2B4Erq7BYBuzsdiH1jCAzoSfl0rVirNbRXlBBlLX%2BBP0XJLAPGzTkAuAOqb0WT5AH7OcdCm5B8TgRwSRKIHQtaLCwg1RAAAOwAAAAAAAAAAAA%3D%3D);visibility:visible;opacity:.6;-webkit-transition:all .3s ease;-moz-transition:all .3s ease;-ms-transition:all .3s ease;transition:all .3s ease}.reveal .preview-link-overlay header{position:absolute;left:0;top:0;width:100%;height:40px;z-index:2;border-bottom:1px solid #222}.reveal .preview-link-overlay header a{display:inline-block;width:40px;height:40px;padding:0 10px;float:right;opacity:.6;box-sizing:border-box}.reveal .preview-link-overlay header a:hover{opacity:1}.reveal .preview-link-overlay header a .icon{display:inline-block;width:20px;height:20px;background-position:50% 50%;background-size:100%;background-repeat:no-repeat}.reveal .preview-link-overlay header a.close .icon{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABkklEQVRYR8WX4VHDMAxG6wnoJrABZQPYBCaBTWAD2g1gE5gg6OOsXuxIlr40d81dfrSJ9V4c2VLK7spHuTJ/5wpM07QXuXc5X0opX2tEJcadjHuV80li/FgxTIEK/5QBCICBD6xEhSMGHgQPgBgLiYVAB1dpSqKDawxTohFw4JSEA3clzgIBPCURwE2JucBR7rhPJJv5OpJwDX+SfDjgx1wACQeJG1aChP9K/IMmdZ8DtESV1WyP3Bt4MwM6sj4NMxMYiqUWHQu4KYA/SYkIjOsm3BXYWMKFDwU2khjCQ4ELJUJ4SmClRArOCmSXGuKma0fYD5CbzHxFpCSGAhfAVSSUGDUk2BWZaff2g6GE15BsBQ9nwmpIGDiyHQddwNTMKkbZaf9fajXQca1EX44puJZUsnY0ObGmITE3GVLCbEhQUjGVt146j6oasWN+49Vph2w1pZ5EansNZqKBm1txbU57iRRcZ86RWMDdWtBJUHBHwoQPi1GV+JCbntmvok7iTX4/Up9mgyTc/FJYDTcndgH/AA5A/CHsyEkVAAAAAElFTkSuQmCC)}.reveal .preview-link-overlay header a.external .icon{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAcElEQVRYR+2WSQoAIQwEzf8f7XiOMkUQxUPlGkM3hVmiQfQR9GYnH1SsAQlI4DiBqkCMoNb9y2e90IAEJPAcgdznU9+engMaeJ7Azh5Y1U67gAho4DqBqmB1buAf0MB1AlVBek83ZPkmJMGc1wAR+AAqod/B97TRpQAAAABJRU5ErkJggg==)}.reveal .preview-link-overlay .viewport{position:absolute;top:40px;right:0;bottom:0;left:0}.reveal .preview-link-overlay .viewport iframe{width:100%;height:100%;max-width:100%;max-height:100%;border:0;opacity:0;visibility:hidden;-webkit-transition:all .3s ease;-moz-transition:all .3s ease;-ms-transition:all .3s ease;transition:all .3s ease}.reveal .preview-link-overlay.loaded .viewport iframe{opacity:1;visibility:visible}.reveal .preview-link-overlay.loaded .spinner{opacity:0;visibility:hidden;-webkit-transform:scale(0.2);-moz-transform:scale(0.2);-ms-transform:scale(0.2);transform:scale(0.2)}.reveal aside.notes{display:none}.zoomed .reveal *,.zoomed .reveal :before,.zoomed .reveal :after{-webkit-transform:none!important;-moz-transform:none!important;-ms-transform:none!important;transform:none!important;-webkit-backface-visibility:visible!important;-moz-backface-visibility:visible!important;-ms-backface-visibility:visible!important;backface-visibility:visible!important}.zoomed .reveal .progress,.zoomed .reveal .controls{opacity:0}.zoomed .reveal .roll span{background:0}.zoomed .reveal .roll span:after{visibility:hidden} \ No newline at end of file diff --git a/asm-talk/css/zenburn.css b/asm-talk/css/zenburn.css new file mode 100644 index 0000000..5392872 --- /dev/null +++ b/asm-talk/css/zenburn.css @@ -0,0 +1,120 @@ +/* + +Zenburn style from voldmar.ru (c) Vladimir Epifanov +based on dark.css by Ivan Sagalaev + +*/ + +pre code { + display: block; padding: 0.5em; + width: 100%; + background: #3F3F3F; + color: #DCDCDC; +} + +.reveal pre code { + width: 100%; +} + +pre .keyword, +pre .tag, +pre .css .class, +pre .css .id, +pre .lisp .title, +pre .nginx .title, +pre .request, +pre .status, +pre .clojure .attribute { + color: #E3CEAB; +} + +pre .django .template_tag, +pre .django .variable, +pre .django .filter .argument { + color: #DCDCDC; +} + +pre .number, +pre .date { + color: #8CD0D3; +} + +pre .dos .envvar, +pre .dos .stream, +pre .variable, +pre .apache .sqbracket { + color: #EFDCBC; +} + +pre .dos .flow, +pre .diff .change, +pre .python .exception, +pre .python .built_in, +pre .literal, +pre .tex .special { + color: #EFEFAF; +} + +pre .diff .chunk, +pre .subst { + color: #8F8F8F; +} + +pre .dos .keyword, +pre .python .decorator, +pre .title, +pre .haskell .type, +pre .diff .header, +pre .ruby .class .parent, +pre .apache .tag, +pre .nginx .built_in, +pre .tex .command, +pre .prompt { + color: #efef8f; +} + +pre .dos .winutils, +pre .ruby .symbol, +pre .ruby .symbol .string, +pre .ruby .string { + color: #DCA3A3; +} + +pre .diff .deletion, +pre .string, +pre .tag .value, +pre .preprocessor, +pre .built_in, +pre .sql .aggregate, +pre .javadoc, +pre .smalltalk .class, +pre .smalltalk .localvars, +pre .smalltalk .array, +pre .css .rules .value, +pre .attr_selector, +pre .pseudo, +pre .apache .cbracket, +pre .tex .formula { + color: #CC9393; +} + +pre .shebang, +pre .diff .addition, +pre .comment, +pre .java .annotation, +pre .template_comment, +pre .pi, +pre .doctype { + color: #7F9F7F; +} + +pre .coffeescript .javascript, +pre .javascript .xml, +pre .tex .formula, +pre .xml .javascript, +pre .xml .vbscript, +pre .xml .css, +pre .xml .cdata { + opacity: 0.5; +} + diff --git a/asm-talk/examples/hello_world/.gitignore b/asm-talk/examples/hello_world/.gitignore new file mode 100644 index 0000000..c357662 --- /dev/null +++ b/asm-talk/examples/hello_world/.gitignore @@ -0,0 +1,16 @@ +.repl_history +build +tags +app/pixate_code.rb +resources/*.nib +resources/*.momd +resources/*.storyboardc +.DS_Store +nbproject +.redcar +#*# +*~ +*.sw[po] +.eprj +.sass-cache +.idea diff --git a/asm-talk/examples/hello_world/Gemfile.lock b/asm-talk/examples/hello_world/Gemfile.lock new file mode 100644 index 0000000..27b0dd7 --- /dev/null +++ b/asm-talk/examples/hello_world/Gemfile.lock @@ -0,0 +1,12 @@ +GEM + remote: https://rubygems.org/ + specs: + rake (10.1.0) + sugarcube (1.0.3) + +PLATFORMS + ruby + +DEPENDENCIES + rake + sugarcube diff --git a/asm-talk/examples/hello_world/app/app_delegate.rb b/asm-talk/examples/hello_world/app/app_delegate.rb new file mode 100644 index 0000000..aee9141 --- /dev/null +++ b/asm-talk/examples/hello_world/app/app_delegate.rb @@ -0,0 +1,8 @@ +class AppDelegate + def application(application, didFinishLaunchingWithOptions:launchOptions) + @window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds) + @window.rootViewController = HelloWorldController.new + @window.makeKeyAndVisible + true + end +end \ No newline at end of file diff --git a/asm-talk/examples/hello_world/app/hello_world_controller.rb b/asm-talk/examples/hello_world/app/hello_world_controller.rb new file mode 100644 index 0000000..c38840c --- /dev/null +++ b/asm-talk/examples/hello_world/app/hello_world_controller.rb @@ -0,0 +1,16 @@ +class HelloWorldController < UIViewController + def viewDidLoad + p "Hello World" + +# view.backgroundColor = UIColor.whiteColor +# center_x = view.frame.size.width / 2 +# center_y = view.frame.size.height / 2 + +# @label = UILabel.new +# @label.text = "Hello World" +# @label.sizeToFit +# @label.center = [center_x, center_y] + +# view.addSubview(@label) + end +end \ No newline at end of file diff --git a/asm-talk/examples/hello_world/resources/Default-568h@2x.png b/asm-talk/examples/hello_world/resources/Default-568h@2x.png new file mode 100644 index 0000000..90a0712 Binary files /dev/null and b/asm-talk/examples/hello_world/resources/Default-568h@2x.png differ diff --git a/asm-talk/examples/hello_world/spec/main_spec.rb b/asm-talk/examples/hello_world/spec/main_spec.rb new file mode 100644 index 0000000..6aa37cf --- /dev/null +++ b/asm-talk/examples/hello_world/spec/main_spec.rb @@ -0,0 +1,9 @@ +describe "Application 'hello_world'" do + before do + @app = UIApplication.sharedApplication + end + + it "has one window" do + @app.windows.size.should == 1 + end +end diff --git a/asm-talk/examples/joybox_physics.mp4 b/asm-talk/examples/joybox_physics.mp4 new file mode 100644 index 0000000..26fb436 Binary files /dev/null and b/asm-talk/examples/joybox_physics.mp4 differ diff --git a/asm-talk/examples/rubytrivia/.gitignore b/asm-talk/examples/rubytrivia/.gitignore new file mode 100644 index 0000000..22b963f --- /dev/null +++ b/asm-talk/examples/rubytrivia/.gitignore @@ -0,0 +1,19 @@ +.repl_history +build +tags +app/pixate_code.rb +resources/*.nib +resources/*.momd +resources/*.storyboardc +.DS_Store +nbproject +.redcar +#*# +*~ +*.sw[po] +.eprj +.sass-cache +.idea +.dat* +provisioning +.datd7c0.000 diff --git a/asm-talk/examples/rubytrivia/.ruby-version b/asm-talk/examples/rubytrivia/.ruby-version new file mode 100644 index 0000000..cb50681 --- /dev/null +++ b/asm-talk/examples/rubytrivia/.ruby-version @@ -0,0 +1 @@ +2.0.0-p247 diff --git a/asm-talk/examples/rubytrivia/.travis.yml b/asm-talk/examples/rubytrivia/.travis.yml new file mode 100644 index 0000000..bc288ca --- /dev/null +++ b/asm-talk/examples/rubytrivia/.travis.yml @@ -0,0 +1,2 @@ +language: objective-c +before_install: rvm use ruby-1.9.3-p392 diff --git a/asm-talk/examples/rubytrivia/Gemfile.lock b/asm-talk/examples/rubytrivia/Gemfile.lock new file mode 100644 index 0000000..b1574cf --- /dev/null +++ b/asm-talk/examples/rubytrivia/Gemfile.lock @@ -0,0 +1,79 @@ +GEM + remote: https://rubygems.org/ + specs: + ProMotion (1.0.4) + activesupport (3.2.14) + i18n (~> 0.6, >= 0.6.4) + multi_json (~> 1.0) + addressable (2.3.5) + awesome_print_motion (0.1.0) + bubble-wrap (1.3.0) + choice (0.1.6) + faraday (0.8.8) + multipart-post (~> 1.2.0) + formotion (1.5.0) + bubble-wrap (~> 1.3.0) + motion-require (~> 0.0.3) + git (1.2.6) + httmultiparty (0.3.10) + httparty (>= 0.7.3) + multipart-post + httparty (0.11.0) + multi_json (~> 1.0) + multi_xml (>= 0.5.2) + i18n (0.6.5) + json (1.7.7) + launchy (2.2.0) + addressable (~> 2.3) + lolcommits (0.4.6) + activesupport (~> 3.2.12) + choice (~> 0.1.6) + git (~> 1.2.5) + httmultiparty + json (~> 1.7.6) + launchy (~> 2.2.0) + methadone (~> 1.2.4) + mini_magick (~> 3.5) + oauth + open4 (~> 1.3.0) + rest-client + twitter + methadone (1.2.6) + bundler + mime-types (1.25) + mini_magick (3.6.0) + subexec (~> 0.2.1) + motion-map (0.0.4) + motion-redgreen (0.1.0) + motion-require (0.0.7) + multi_json (1.7.9) + multi_xml (0.5.5) + multipart-post (1.2.0) + oauth (0.4.7) + open4 (1.3.0) + rake (10.1.0) + rest-client (1.6.7) + mime-types (>= 1.16) + simple_oauth (0.2.0) + subexec (0.2.3) + sugarcube (1.1.0) + teacup (2.1.9) + twitter (4.8.1) + faraday (~> 0.8, < 0.10) + multi_json (~> 1.0) + simple_oauth (~> 0.2) + +PLATFORMS + ruby + +DEPENDENCIES + ProMotion + awesome_print_motion + bubble-wrap + formotion + lolcommits + motion-map + motion-redgreen + rake + sugarcube + teacup diff --git a/asm-talk/examples/rubytrivia/README.md b/asm-talk/examples/rubytrivia/README.md new file mode 100644 index 0000000..ecfad4a --- /dev/null +++ b/asm-talk/examples/rubytrivia/README.md @@ -0,0 +1,9 @@ +RubyTrivia +========== +[![Build Status](https://travis-ci.org/IconoclastLabs/rubytrivia.png?branch=master)](https://travis-ci.org/IconoclastLabs/rubytrivia) + +Simple ProMotion app, based off of [gregstallings ruby-trivia](https://github.com/gregstallings/ruby-trivia) + +View [Github Page](http://iconoclastlabs.github.io/rubytrivia/) + +![RubyTrivia](./resources/Default-568h@2x.png "Screenshot") diff --git a/asm-talk/examples/rubytrivia/app/app_delegate.rb b/asm-talk/examples/rubytrivia/app/app_delegate.rb new file mode 100644 index 0000000..223e24c --- /dev/null +++ b/asm-talk/examples/rubytrivia/app/app_delegate.rb @@ -0,0 +1,9 @@ +class AppDelegate < PM::Delegate + + status_bar false, animation: :none + + def on_load(app, options) + open QuestionScreen.new(nav_bar: true) + end + +end diff --git a/asm-talk/examples/rubytrivia/app/lib/trivia_modal_module.rb b/asm-talk/examples/rubytrivia/app/lib/trivia_modal_module.rb new file mode 100644 index 0000000..5faa46b --- /dev/null +++ b/asm-talk/examples/rubytrivia/app/lib/trivia_modal_module.rb @@ -0,0 +1,16 @@ +module TriviaModal + + def on_load + # Close modal on tap or swipe + view.on_tap do + close + end + view.on_swipe :left do + close + end + view.on_swipe :right do + close + end + end + +end \ No newline at end of file diff --git a/asm-talk/examples/rubytrivia/app/lib/uilabel.rb b/asm-talk/examples/rubytrivia/app/lib/uilabel.rb new file mode 100644 index 0000000..67f24ec --- /dev/null +++ b/asm-talk/examples/rubytrivia/app/lib/uilabel.rb @@ -0,0 +1,39 @@ +class UILabel + + unless UILabel.instance_methods.include? :code_style + def code_style text + return if text.nil? + self.text = text + self.fit_to_size(40) # make it fit + + # prepare the vars + ranges = [] + current_s = "" + # find code and fill ranges array + text.strip.split(/`/).each_with_index do |text_slice, index| + if index.even? + # Non-code elements just get added + current_s += text_slice + else + # remove backticks and save position while adding + code = text_slice.gsub("`", "") + start_pos = current_s.length + end_pos = start_pos + code.length - 1 + current_s += code + ranges.push(start_pos..end_pos) #store range + end + end + + font_attrs = MotionMap::Map[NSFontAttributeName, UIFont.fontWithName( 'CourierNewPSMT', size: (self.font.pointSize - 2) )] + string_styled = NSMutableAttributedString.alloc.initWithString( current_s, attributes: nil ).tap do |attrs| + ranges.each do |code_range| + attrs.setAttributes( font_attrs, range: code_range) + end + end + + self.attributedText = string_styled + end + + end + +end \ No newline at end of file diff --git a/asm-talk/examples/rubytrivia/app/models/trivia.rb b/asm-talk/examples/rubytrivia/app/models/trivia.rb new file mode 100644 index 0000000..75a27bb --- /dev/null +++ b/asm-talk/examples/rubytrivia/app/models/trivia.rb @@ -0,0 +1,73 @@ +class Trivia + attr_reader :current_quip + + def initialize + @current_quip = {"answer"=>"Begin swiping to get started!", "question"=>"Welcome to Ruby Trivia!"} + App::Persistence['trivia'] ||= self.seed_quips + @quips = App::Persistence['trivia'].dup + @current_position = 0 + filter_quips + perform_update + end + + def previous + @current_position = (@current_position - 1) % @lines.size + @current_quip = @lines[@current_position.abs] + end + + def next + # iterate, but wrap around when you hit size + @current_position = (@current_position + 1) % @lines.size + @current_quip = @lines[@current_position] + end + + def filter_quips + # Populate lines from live categories + @lines = [] #make sure it's empty + cat_settings = App::Persistence["FORMOTION_settings"] + + # If settings have been modified, use those; otherwise just add all questions + categories.each do |cat| + if cat_settings + @lines += @quips[cat] if cat_settings[clean_symbol(cat)] + else + @lines += @quips[cat] + end + end + + @lines.shuffle! + @lines.push({"answer"=>"Click on About -> Settings!", "question"=>"No Categories Selected"}) if @lines.empty? + ap "Filtered Lines! Count = #{@lines.size}" + end + + def seed_quips + ap "Seed quips called" + seed_file = NSBundle.mainBundle.pathForResource('qa', ofType:'json') + json_string = String.new(NSString.stringWithContentsOfFile(seed_file)) + BW::JSON.parse(json_string) + end + + def categories + @quips.keys.sort + end + + def perform_update + ap "downloading update" + BW::HTTP.get("https://raw.github.com/IconoclastLabs/rubytrivia/master/resources/qa.json") do |response| + if response.ok? + ap "Download complete and ok. Now setting it to the new file" + App::Persistence['trivia'] = BW::JSON.parse(response.body.to_str) + else + ap "Download Failed: #{response.error_message}" + false + end + end + + end + + def clean_symbol string + #only word characters, lowercased + string.gsub(/\W+/, "").downcase.to_sym + end + +end \ No newline at end of file diff --git a/asm-talk/examples/rubytrivia/app/screens/about_screen.rb b/asm-talk/examples/rubytrivia/app/screens/about_screen.rb new file mode 100644 index 0000000..74572b8 --- /dev/null +++ b/asm-talk/examples/rubytrivia/app/screens/about_screen.rb @@ -0,0 +1,54 @@ +class AboutScreen < PM::GroupedTableScreen + stylesheet :trivia_stylesheet + attr_accessor :trivia + title "About" + + def table_data + @credit_table_data ||= [ + { + title: "Code", + cells: [ + { title: "Written by Iconoclast Labs", action: :email_us}, + { title: "Code framework ProMotion", action: :view_page, arguments: { site: "http://clearsightstudio.github.io/ProMotion/"}}, + { title: "Language RubyMotion", action: :view_page, arguments: { site: "http://www.rubymotion.com/"}}, + { title: "View site and code", action: :view_page, arguments: { site: "http://iconoclastlabs.github.io/rubytrivia/"}} + ] + },{ + title: "Graphics", + cells: [ + { title: "Background: SubtlePatterns.com", action: :view_page, arguments: { site: "http://subtlepatterns.com/retina-wood/"}}, + { title: "Icon Julien Deveaux : NounProject", action: :view_page, arguments: { site: "http://thenounproject.com/noun/ruby/#icon-No15720"}}, + { title: "Formatting with Teacup", action: :view_page, arguments: { site: "https://github.com/rubymotion/teacup"}} + ] + },{ + title: "Questions", + cells: [ + { title: "GitHub gregstallings/ruby-trivia", action: :view_page, arguments: { site: "https://github.com/gregstallings/ruby-trivia"}}, + { title: "Configure Questions", action: :settings_modal} + ] + } + ] + + end + + def will_appear + view.backgroundView = nil # WAS NEEDED FOR iOS6 + set_attributes self.view, stylename: :trivia_view + end + + def email_us + mailto_link = "mailto:developers@iconoclastlabs.com".nsurl + UIApplication.sharedApplication.openURL(mailto_link) + end + + def view_page(args={}) + args[:site].nsurl.open + end + + def settings_modal + ap "Show Settings" + open_modal SettingsScreen.new(nav_bar: true, trivia: @trivia) + end + + +end diff --git a/asm-talk/examples/rubytrivia/app/screens/modals/answer_screen.rb b/asm-talk/examples/rubytrivia/app/screens/modals/answer_screen.rb new file mode 100644 index 0000000..347f7fd --- /dev/null +++ b/asm-talk/examples/rubytrivia/app/screens/modals/answer_screen.rb @@ -0,0 +1,19 @@ +class AnswerScreen < PM::Screen + include TriviaModal + stylesheet :trivia_stylesheet + title "Answer" + attr_accessor :answer + + def will_appear + @view_is_set_up ||= set_up_view + @label.code_style(answer) + ap "Answer will appear" + end + + def set_up_view + set_attributes self.view, stylename: :trivia_view + add @label = UILabel.new, stylename: :my_label + true + end + +end diff --git a/asm-talk/examples/rubytrivia/app/screens/modals/help_screen.rb b/asm-talk/examples/rubytrivia/app/screens/modals/help_screen.rb new file mode 100644 index 0000000..347fd40 --- /dev/null +++ b/asm-talk/examples/rubytrivia/app/screens/modals/help_screen.rb @@ -0,0 +1,25 @@ +class HelpScreen < PM::Screen + include TriviaModal + stylesheet :trivia_stylesheet + title "Help" + + def will_appear + @view_is_set_up ||= set_up_view + end + + def set_up_view + set_attributes self.view, stylename: :trivia_view + set_nav_bar_button :left, title: "Close", action: :close_modal_tapped + add UIImageView.alloc.initWithImage('swipe.png'.uiimage), stylename: :swipe_help + add UIImageView.alloc.initWithImage('tap.png'.uiimage), stylename: :tap_help + add UIImageView.alloc.initWithImage('previous.png'.uiimage), stylename: :previous_help + add labs = UIImageView.alloc.initWithImage('footer.png'.uiimage), stylename: :footer_help + + true + end + + def close_modal_tapped + close + end + +end diff --git a/asm-talk/examples/rubytrivia/app/screens/modals/settings_screen.rb b/asm-talk/examples/rubytrivia/app/screens/modals/settings_screen.rb new file mode 100644 index 0000000..0909d05 --- /dev/null +++ b/asm-talk/examples/rubytrivia/app/screens/modals/settings_screen.rb @@ -0,0 +1,55 @@ +class SettingsScreen < PM::FormotionScreen + stylesheet :trivia_stylesheet + attr_accessor :trivia + title "Settings" + + def will_appear + @view_is_set_up ||= set_up_view + end + + def set_up_view + set_attributes self.view, stylename: :trivia_view + set_nav_bar_button :left, title: "Close", action: :close_modal_tapped + # clear out the normal striped background for iOS6 + self.view.backgroundView = nil + set_attributes self.view, stylename: :trivia_view + true + end + + def table_data + { + title: "Settings", + persist_as: :settings, + sections: [{ + title: "Question Categories", + rows: category_rows + }] + } + end + + def will_disappear + @trivia.filter_quips + end + + private + + def category_rows + all_categories = [] + @trivia.categories.each do |category| + all_categories << { + title: category, + key: @trivia.clean_symbol(category), + type: :switch, + value: true + } + end + all_categories + end + + def close_modal_tapped + close + end + + + +end \ No newline at end of file diff --git a/asm-talk/examples/rubytrivia/app/screens/question_screen.rb b/asm-talk/examples/rubytrivia/app/screens/question_screen.rb new file mode 100644 index 0000000..78ec6b3 --- /dev/null +++ b/asm-talk/examples/rubytrivia/app/screens/question_screen.rb @@ -0,0 +1,68 @@ +class QuestionScreen < PM::Screen + stylesheet :trivia_stylesheet + title "Ruby Trivia" + + def will_appear + @view_setup ||= set_up_view + # just in-case orientation changed while away + self.view.restyle! + @label.code_style(@trivia.current_quip["question"]) + end + + def set_up_view + set_nav_bar_button :left, title: "Help", action: :help_tapped + set_nav_bar_button :right, title: "About", action: :about_tapped + set_attributes self.view, stylename: :trivia_view + add @label = UILabel.new, stylename: :my_label + # our trivia engine + @trivia = Trivia.new + + view.on_tap do + ap "Tapped: Show Answer" + open_modal AnswerScreen.new(nav_bar: true, + transition_style: UIModalTransitionStyleFlipHorizontal, + presentation_style: UIModalPresentationFormSheet, + answer: @trivia.current_quip["answer"]) + end + + view.on_swipe :left do + ap "Swiped: Show Next" + new_question(@label, @trivia.next["question"]) + end + + view.on_swipe :right do + ap "Swiped: Show Previous" + new_question(@label, @trivia.previous["question"], :right) + end + true + end + + private + + def new_question (question_view, new_question, swipe_direction = :left) + start_frame = question_view.frame + # simply slides away the current question with a fade, + # invisibly sets the new text and fades it in + # ~ thank you sugarcube! + UIView.animation_chain do + question_view.fade_out + question_view.slide swipe_direction + end.and_then do + question_view.code_style(new_question) + question_view.frame = start_frame + end.and_then do + question_view.fade_in + end.start + end + + def about_tapped + ap "About Called" + open AboutScreen.new(nav_bar: true, trivia: @trivia) + end + + def help_tapped + ap "Help Called" + open_modal HelpScreen.new(nav_bar: true) + end + +end diff --git a/asm-talk/examples/rubytrivia/app/styles/base_styles.rb b/asm-talk/examples/rubytrivia/app/styles/base_styles.rb new file mode 100644 index 0000000..906d104 --- /dev/null +++ b/asm-talk/examples/rubytrivia/app/styles/base_styles.rb @@ -0,0 +1,15 @@ +Teacup::Stylesheet.new :base_stylesheet do + style :trivia_view, + backgroundColor: 'retina_wood'.uicolor, + landscape: true + + style :help_image, + contentMode: UIViewContentModeScaleAspectFit, + portrait: { + width: '90%' + }, + landscape: { + width: '40%' + } + +end diff --git a/asm-talk/examples/rubytrivia/app/styles/trivia_styles.rb b/asm-talk/examples/rubytrivia/app/styles/trivia_styles.rb new file mode 100644 index 0000000..f51ea1b --- /dev/null +++ b/asm-talk/examples/rubytrivia/app/styles/trivia_styles.rb @@ -0,0 +1,57 @@ +Teacup::Stylesheet.new :trivia_stylesheet do + import :base_stylesheet + + style :my_label, + backgroundColor: UIColor.clearColor, + numberOfLines: 0, + textAlignment: UITextAlignmentCenter, + font: UIFont.boldSystemFontOfSize(40), + portrait: { + width: '90%', + height: '85%', + center: ['50%', '55%'] + }, + landscape: { + width: '90%', + height: '85%', + center: ['50%', '55%'] + } + + +############## Help Screen ################ + style :swipe_help, extends: :help_image, + portrait: { + center: ['50%','25%'] + }, + landscape: { + center: ['25%','30%'] + } + + style :tap_help, extends: :help_image, + portrait: { + center: ['50%','47%'] + }, + landscape: { + center: ['50%','55%'] + } + + style :previous_help, extends: :help_image, + portrait: { + center: ['50%','70%'] + }, + landscape: { + center: ['75%','80%'] + } + + style :footer_help, + contentMode: UIViewContentModeScaleAspectFit, + portrait: { + width: '100%', + hidden: false, + center: ['50%','92%'] + }, + landscape: { + hidden: true + } + +end diff --git a/asm-talk/examples/rubytrivia/app_properties.rb b/asm-talk/examples/rubytrivia/app_properties.rb new file mode 100644 index 0000000..3cccc38 --- /dev/null +++ b/asm-talk/examples/rubytrivia/app_properties.rb @@ -0,0 +1,64 @@ +class AppProperties + VERSION = '1.1' + SKU_NAME = 'rubytrivia' #default + COMPANY_NAME = 'com.iconoclastlabs.' + + def name + 'Ruby Trivia' + end + + def self.version + VERSION + end + + def app_version + VERSION + end + + def frameworks + [] + end + + def contributors + ["Gant Laborde", "Matt Garrison"] + end + + def developer_certificate + "iPhone Developer: Gant Laborde (56HAJP2GEQ)" #"iPhone Developer: Matt Garrison (EUS6PB7N8V)" + end + + def distribution_certificate + "iPhone Distribution: Iconoclast Labs LLC" + end + + def provisioning + './provisioning' #symlink is custom to each user's machine + end + + def deployment_target + '6.0' + end + + + def delegate + 'app_delegate' + end + + def prerendered_icon + false + end + + def devices + [:iphone] + end + + def identifier + COMPANY_NAME + SKU_NAME + end + + def description + %W[ + A basic flashcard app for Ruby trivia questions. + ] + end +end diff --git a/asm-talk/examples/rubytrivia/psd/help.psd b/asm-talk/examples/rubytrivia/psd/help.psd new file mode 100644 index 0000000..ac6344c Binary files /dev/null and b/asm-talk/examples/rubytrivia/psd/help.psd differ diff --git a/asm-talk/examples/rubytrivia/psd/rubytrivia.psd b/asm-talk/examples/rubytrivia/psd/rubytrivia.psd new file mode 100644 index 0000000..579848a Binary files /dev/null and b/asm-talk/examples/rubytrivia/psd/rubytrivia.psd differ diff --git a/asm-talk/examples/rubytrivia/resources/Default-568h@2x.png b/asm-talk/examples/rubytrivia/resources/Default-568h@2x.png new file mode 100644 index 0000000..1dec357 Binary files /dev/null and b/asm-talk/examples/rubytrivia/resources/Default-568h@2x.png differ diff --git a/asm-talk/examples/rubytrivia/resources/Icon-72.png b/asm-talk/examples/rubytrivia/resources/Icon-72.png new file mode 100644 index 0000000..5fdcd65 Binary files /dev/null and b/asm-talk/examples/rubytrivia/resources/Icon-72.png differ diff --git a/asm-talk/examples/rubytrivia/resources/Icon-72@2x.png b/asm-talk/examples/rubytrivia/resources/Icon-72@2x.png new file mode 100644 index 0000000..cc79462 Binary files /dev/null and b/asm-talk/examples/rubytrivia/resources/Icon-72@2x.png differ diff --git a/asm-talk/examples/rubytrivia/resources/Icon-Small-50.png b/asm-talk/examples/rubytrivia/resources/Icon-Small-50.png new file mode 100644 index 0000000..6630b20 Binary files /dev/null and b/asm-talk/examples/rubytrivia/resources/Icon-Small-50.png differ diff --git a/asm-talk/examples/rubytrivia/resources/Icon-Small-50@2x.png b/asm-talk/examples/rubytrivia/resources/Icon-Small-50@2x.png new file mode 100644 index 0000000..bac9733 Binary files /dev/null and b/asm-talk/examples/rubytrivia/resources/Icon-Small-50@2x.png differ diff --git a/asm-talk/examples/rubytrivia/resources/Icon-Small.png b/asm-talk/examples/rubytrivia/resources/Icon-Small.png new file mode 100644 index 0000000..3c262e1 Binary files /dev/null and b/asm-talk/examples/rubytrivia/resources/Icon-Small.png differ diff --git a/asm-talk/examples/rubytrivia/resources/Icon-Small@2x.png b/asm-talk/examples/rubytrivia/resources/Icon-Small@2x.png new file mode 100644 index 0000000..e9fd1ad Binary files /dev/null and b/asm-talk/examples/rubytrivia/resources/Icon-Small@2x.png differ diff --git a/asm-talk/examples/rubytrivia/resources/Icon.png b/asm-talk/examples/rubytrivia/resources/Icon.png new file mode 100644 index 0000000..34ca3bf Binary files /dev/null and b/asm-talk/examples/rubytrivia/resources/Icon.png differ diff --git a/asm-talk/examples/rubytrivia/resources/Icon@2x.png b/asm-talk/examples/rubytrivia/resources/Icon@2x.png new file mode 100644 index 0000000..16e35e3 Binary files /dev/null and b/asm-talk/examples/rubytrivia/resources/Icon@2x.png differ diff --git a/asm-talk/examples/rubytrivia/resources/footer.png b/asm-talk/examples/rubytrivia/resources/footer.png new file mode 100644 index 0000000..bf6c3db Binary files /dev/null and b/asm-talk/examples/rubytrivia/resources/footer.png differ diff --git a/asm-talk/examples/rubytrivia/resources/iTunesArtwork.png b/asm-talk/examples/rubytrivia/resources/iTunesArtwork.png new file mode 100644 index 0000000..a75ca60 Binary files /dev/null and b/asm-talk/examples/rubytrivia/resources/iTunesArtwork.png differ diff --git a/asm-talk/examples/rubytrivia/resources/iTunesArtwork@2x.png b/asm-talk/examples/rubytrivia/resources/iTunesArtwork@2x.png new file mode 100644 index 0000000..27fb4ec Binary files /dev/null and b/asm-talk/examples/rubytrivia/resources/iTunesArtwork@2x.png differ diff --git a/asm-talk/examples/rubytrivia/resources/previous.png b/asm-talk/examples/rubytrivia/resources/previous.png new file mode 100644 index 0000000..f89418e Binary files /dev/null and b/asm-talk/examples/rubytrivia/resources/previous.png differ diff --git a/asm-talk/examples/rubytrivia/resources/qa.json b/asm-talk/examples/rubytrivia/resources/qa.json new file mode 100644 index 0000000..9a10efe --- /dev/null +++ b/asm-talk/examples/rubytrivia/resources/qa.json @@ -0,0 +1,838 @@ +{ + "Language Characteristics and Core Objects": [ + { + "question": "What is the highest level in the object model? ", + "answer": "`BasicObject`" + }, + { + "question": "Is everything in Ruby an object? ", + "answer": "Methods are not objects. Blocks are not objects. Keywords are not objects. However, there exist Method objects and Proc objects, and some keywords refer to objects." + }, + { + "question": "Which core object includes the `Kernel` module? ", + "answer": "`Object`" + }, + { + "question": "What can you say about an identifier that begins with a capital letter? ", + "answer": "It is a constant." + }, + { + "question": "What is a DSL and how does it pertain to Ruby? ", + "answer": "A Domain Specific Language is an API that allows a developer to solve a problem or represent data more naturally than they might otherwise. The flexible nature of Ruby's syntax and the ability to alias and alter existing methods and classes makes it conducive to creating rich DSL's." + }, + { + "question": "What is duck typing and how does it pertain to Ruby? ", + "answer": "That an object may be acted upon even if it isn't the expected type as long as it looks and behaves like the expected object. This is a characteristic of Ruby because the lack of type checking of parameters makes this an effective programming technique." + }, + { + "question": "Is Ruby a statically typed or a dynamically typed language? ", + "answer": "Dynamically typed since type checking is done at runtime." + }, + { + "question": "Is Ruby a strongly typed or a weakly typed language? ", + "answer": "Strongly typed since an object's type is checked before an operation is performed on it." + }, + { + "question": "What does it mean to coerce an object? Why would you do it? ", + "answer": "To coerce an object means to force it into an expected type. One might do this in order to try and force an unknown object type into the expected type or format required by the operation. This is a common practice involved in duck typing." + }, + { + "question": "What is the difference between a statement and an expression in Ruby? ", + "answer": "All statements are expressions in Ruby since all statements return a value." + } + ], + "Data Types": [ + { + "question": "Why might you want to avoid using string literals within loops? ", + "answer": "A new object is created for every string literal even when the values are identical. Consider using variables or symbols instead." + }, + { + "question": "Does `String` include the `Enumerable` module? ", + "answer": "No." + }, + { + "question": "What method might you use to enumerate over a string? ", + "answer": "`String#each_char`" + }, + { + "question": "What is the difference between a character literal such as `?A` and a string literal such as `'A'`? ", + "answer": "There is no difference." + }, + { + "question": "Describe a symbol. ", + "answer": "Symbols are scalar value objects used as identifiers, mapping immutable strings to fixed internal values." + }, + { + "question": "Why are symbols typically used as hash keys instead of strings? ", + "answer": "Strings are mutable while symbols are immutable. Though Ruby internally makes an immutable copy of a string when used as a hash key, comparing two symbols is faster than comparing two `String` objects. This is also a convention." + }, + { + "question": "Symbols are immutable objects. Name another immutable core Ruby object. ", + "answer": "`Fixnum`" + }, + { + "question": "What happens when a value becomes too big for `Fixnum`? ", + "answer": "It is automatically converted to a `Bignum`." + }, + { + "question": "What is the superclass of `Fixnum`? ", + "answer": "`Integer`" + }, + { + "question": "What is the superclass of `Integer`? ", + "answer": "`Numeric`" + }, + { + "question": "What numeric class might you use to avoid the rounding error arising in the use of binary floating-point arithmetic? ", + "answer": "`BigDecimal`" + }, + { + "question": "How does the `%W` syntax differ from the `%w` syntax? ", + "answer": "With `%W` it is possible to define an array containing string interpolation." + }, + { + "question": "Name at least one synonym for `Hash#key?`? ", + "answer": "`Hash#has_key?`, `Hash#include?`, `Hash#member?`" + }, + { + "question": "How might you specify a default value for a hash? ", + "answer": "Pass the default values as arguments to `::new` on initialization or change the default directly with the setter method `Hash#default`. You may also provide a default at time of query using `Hash#fetch`." + }, + { + "question": "Does `Hash` use `#==` or `#eql?` to compare hash keys? ", + "answer": "`#eql?`" + }, + { + "question": "In what order are the values of a hash iterated? ", + "answer": "The order in which they were inserted." + }, + { + "question": "What is the synonym of `Hash#[]=`? ", + "answer": "`Hash#store`" + }, + { + "question": "Why can you safely use a string as a hash key, even though a string is mutable? ", + "answer": "Because the interpreter makes a private copy of a string used as a hash key." + }, + { + "question": "Why might you use `Hash#fetch` over `Hash#[]` when querying values in a hash? ", + "answer": "`Hash#fetch` provides options for handling the case where a key does not exist in the hash." + }, + { + "question": "When would you need to use `Hash#rehash`? ", + "answer": "After you mutate a mutable hash key." + }, + { + "question": "What are two uses of ranges? ", + "answer": "comparison, iteration" + }, + { + "question": "How might you include an expression within a `Regexp` literal? ", + "answer": "Using `#{}` just like as in a double-quoted string literal." + }, + { + "question": "What is the global variable for the last `Regexp` match? ", + "answer": "`$LAST_MATCH_INFO` equivalent to `$~`" + } + ], + "Operators": [ + { + "question": "What are two uses of the splat operator? ", + "answer": "Explode or expand the elements of an array. Collect arguments of a parameter list into an array." + }, + { + "question": "What is the only operator which accepts three operands? ", + "answer": "The conditional operator `?:` (sometimes referred to as the ternary if operator)." + }, + { + "question": "Which operator must be defined in order to implement the `Comparable` module? ", + "answer": "`<=>`" + }, + { + "question": "What is the difference between `#==` and `#equal?`? ", + "answer": "`#==` performs the generic comparison and is implemented differently across classes while `#equal?` is defined on `BasicObject` and compares object identity. Therefore, `#equal?` should not be overridden in subclasses." + }, + { + "question": "What is the difference between `#==` and `#===`? ", + "answer": "`#==` performs the generic comparison while `#===` performs case equality comparison and is useful for providing meaningful semantics in case statements." + }, + { + "question": "What is the difference between `#==` and `#eql?`? ", + "answer": "`#eql?` is sometimes an alternate equality. `Hash` uses `#eql?` to test for hash key equality. `Numeric` types perform type conversion across `#==` but not across `#eql?`, thus `#eql?` performs a stricter comparison than `#==` in that case." + }, + { + "question": "Which binds more tightly? `&&` or `and` ", + "answer": "`&&`" + }, + { + "question": "Which binds more tightly? `&&` or `=` ", + "answer": "`&&`" + }, + { + "question": "Which binds more tightly? `and` or `=` ", + "answer": "`=`" + }, + { + "question": "Which binds more tightly? `&&` or `||` ", + "answer": "`&&`" + } + ], + "Control Structures": [ + { + "question": "What is a statement modifier? ", + "answer": "A condition which follows a statement such as with `x = 1 if a == true`" + }, + { + "question": "Does a while block define a new scope? ", + "answer": "No." + }, + { + "question": "Does the case statement in Ruby have fall-through behavior? ", + "answer": "No." + }, + { + "question": "What is the difference between `throw/catch` and `raise/rescue`? ", + "answer": "`throw` and `catch` accept matching symbols as arguments and should be considered a control-flow structure where `raise` and `rescue` is used to raise and handle exceptions. `throw` and `catch` are not commonly used while exception handling with `raise` and `rescue` is used often." + }, + { + "question": "Does a `rescue` block define a new scope? ", + "answer": "No." + }, + { + "question": "What are some advantages of a case statement versus repeated `elsif` statements? ", + "answer": "It shows intent. It DRY's out the condition." + }, + { + "question": "What are some disadvantages of a case statement versus repeated `elsif` statements? ", + "answer": "The statement is typically resistant to modification without a complete refactoring of the entire control structure. The case statement can be confusing if multiple comma-separated expressions are associated with a single when clause." + } + ], + "Blocks and Iterators": [ + { + "question": "Name at least two classes which include the `Enumerable` module. ", + "answer": "`Array`, `Hash`, `Range`, `IO`..." + }, + { + "question": "When might you use the `do`/`end` syntax versus using the curly bracket syntax for a block? ", + "answer": "The `do`/`end` syntax for a block is commonly used for multi-line statements. An alternate convention is to use curly bracket syntax for blocks that return a value while using `do`/`end` syntax for blocks that change the state of the system somehow and do not return a value." + }, + { + "question": "What is an iterator? ", + "answer": "An object that allows traversal of the elements of the container. In Ruby, an iterator is typically considered any method that uses the yield statement." + }, + { + "question": "How do you define block-local variables within a block's parameter list? ", + "answer": "Variables that appear after a semicolon in a block's parameter list are guaranteed to be local to the block." + }, + { + "question": "What is the synonym of `#include?`? ", + "answer": "`Enumerable#member?`" + }, + { + "question": "Can a collection be modified while it is being iterated upon? ", + "answer": "Yes." + }, + { + "question": "Is a block an object? ", + "answer": "No. A block is a syntactic structure of the interpreter. A block can be converted to a Proc object." + }, + { + "question": "What is the synonym of `Enumberable#collect`? ", + "answer": "`Enumberable#map`" + }, + { + "question": "What is the synonym of `Enumberable#find`? ", + "answer": "`Enumberable#detect`" + }, + { + "question": "What is the synonym of `Enumberable#select`? ", + "answer": "`Enumberable#find_all`" + }, + { + "question": "What is the opposite of `Enumberable#select`? ", + "answer": "`Enumberable#reject`" + }, + { + "question": "What is the synonym of `Enumberable#inject`? ", + "answer": "`Enumberable#reduce`" + }, + { + "question": "Why might you use `#each` instead of `for/in`? ", + "answer": "It's the 'Ruby way' - an example of how Ruby defines methods that mimic natural language concepts. Iterator methods such as `#each` read more naturally. `#each` is a block so it defines a new variable scope. `for/in` depends on the existence of `#each` which implies that `#each` is a more fundamental aspect of the language." + }, + { + "question": "What happens if a block is passed two arguments but only accepts one argument? ", + "answer": "Nothing. Only the first argument will be passed to the block." + }, + { + "question": "How is a block anonymous? ", + "answer": "It doesn't have a name. It doesn't exist beyond it's execution unless converted to a Proc object." + }, + { + "question": "How does block invocation differ from method invocation? ", + "answer": "Ruby will throw an exception if more than the expected number of arguments are passed to a method. A block will simply ignore the extra values." + } + ], + "Methods": [ + { + "question": "Does Ruby support method overloading? ", + "answer": "No." + }, + { + "question": "How might you test the presence of a method? ", + "answer": "`Object#respond_to?` or `Module#method_defined?`" + }, + { + "question": "What is the meaning of `self`? ", + "answer": "The current object." + }, + { + "question": "What does a bang `!` at the end of a method signify? ", + "answer": "That it should be used with caution. Methods with this naming convention typically perform a mutation on the receiver object." + }, + { + "question": "What is a mutator method? ", + "answer": "A method which alters the internal state of the object receiver." + }, + { + "question": "Is a method an object? ", + "answer": "No, however, a `Method` object is of course, an object." + }, + { + "question": "What is a predicate in the context of Ruby method naming conventions? ", + "answer": "A method that answers a question posed by the method invocation or method name. Predicates typically return a boolean." + }, + { + "question": "Are instance methods public or private? ", + "answer": "They are public by default. You can change their visibility using `Module#private`, `Module#protected`, or back again using `Module#public`." + }, + { + "question": "When might you explicitly use the `return` statement. ", + "answer": "To return from a method prematurely." + }, + { + "question": "Why might you want to alias a method? ", + "answer": "To create a synonym for an existing method that is more readable or appropriate in the context of some problems or to add functionality to an existing method." + }, + { + "question": "How might you send a message to a private method of a receiver object from outside the scope of the receiver object? ", + "answer": "`Object#send`" + }, + { + "question": "How would you typically prevent future modifications to an object? ", + "answer": "`#freeze`" + }, + { + "question": "How is the invocation of a private method different than the invocation of a public method from within its defining class? ", + "answer": "It must be referenced in a functional manner without an explicit receiver object and not on the class object itself or on the current object `self`." + }, + { + "question": "Can method names be capitalized? ", + "answer": "Yes, but the convention is that they are not." + }, + { + "question": "What is the difference between private and protected methods? ", + "answer": "A private method can only be called by any instance methods of the defining class or any subclasses and must be invoked in a functional style and not explicitly on `self` such as with `self.my_method`. A protected method may be explicitly invoked by any instance of the defining class, and is not restricted to implicit invocation on `self`." + }, + { + "question": "What is a singleton method? ", + "answer": "A method that is available only on a single object." + }, + { + "question": "How does `return` differ from within a method than from within a block? ", + "answer": "`return` within a method returns from the method. `return` within a block returns from its lexically enclosing method." + }, + { + "question": "Are class methods public or private? ", + "answer": "They are public by default. You can change their visibility using `#private_class_method` and back again using `#public_class_method`." + }, + { + "question": "Does a method return a value if it does not contain an expression? ", + "answer": "Yes, it returns `nil`." + }, + { + "question": "If a method is declared outside a class or module definition at the top level, where does it live? ", + "answer": "As a private instance method of `Object`, whose value of `self` resolves to the special 'main' object." + }, + { + "question": "What is the origin of the 'keywords' `public`, `private`, and `protected`? ", + "answer": "They are instance methods of the `Module` class. Since `Class` subclasses `Module`, these methods can be invoked without explicit reference to `self` such as `self.private`." + }, + { + "question": "How do you define a private class method? ", + "answer": "Define the class method and call `#private_class_method` with an argument as a symbol of the class method name." + }, + { + "question": "Name at least two ways to disable methods. ", + "answer": "`undef method_name`, `#remove_method`, `#undef_method`" + }, + { + "question": "What is the difference between `#remove_method` and `#undef_method`? ", + "answer": "`#undef_method` prevents any invocation of the method through an instance of the class, while `#remove_method` will remove the method definition from the class, but not prevent inherited methods of the same name from being invoked." + }, + { + "question": "Explain how Ruby syntax supports keyword arguments in parameters lists? ", + "answer": "You can leave off the curly brackets from a hash in a parameter list, assuming it is the last argument in the list." + } + ], + "Procs and Lambdas": [ + { + "question": "What are the two varieties of Proc objects? ", + "answer": "Procs and lambdas." + }, + { + "question": "What can be said about a method argument that is prefixed with `&`? ", + "answer": "It will refer to the calling block as a named Proc object. It must be the last argument in the parameter list." + }, + { + "question": "What is the main difference between procs and lambdas? ", + "answer": "Calling a lambda is more akin to invoking a method where a return statement in a lambda will return from the lambda itself, instead of returning from the lexically enclosing method, as procs do. Adding to this notion, lambdas must be invoked with the exact number of arguments such as is required by method invocation, whereas procs are more flexible in receiving arguments." + }, + { + "question": "Does an object have to be a Proc object for a `&` to be prefixed to it in a parameter list? ", + "answer": "No, `&` can appear before any object with a `#to_proc` method." + }, + { + "question": "What is the difference between Proc invocation and lambda invocation? ", + "answer": "A block must be associated with lambda invocation. Lambdas must be invoked with the exact number of arguments such as is required by method invocation, whereas procs are more flexible in receiving arguments." + }, + { + "question": "When might you encounter a `LocalJumpError`? ", + "answer": "You might typically encounter this exception when attempting to yield when no block is given. You might also encounter this exception when attempting to return from a method that has already returned such as if you attempt to return from a Proc object whose lexically enclosing method has already returned." + } + ], + "Closures": [ + { + "question": "Describe a closure in Ruby. ", + "answer": "A closure is an object that is both an invocable function together with a variable binding. The object retains access to the local variables that were in scope at the time of the object definition." + }, + { + "question": "Does a closure in Ruby retain variables by value or by reference? ", + "answer": "By reference; the closure also extends the lifetimes of its variables." + }, + { + "question": "A closure's reference to its variables is said to by dynamically bound. What does this mean? ", + "answer": "The values of the variables are resolved when the Proc object is executed." + }, + { + "question": "Is it possible to alter a closure? ", + "answer": "Yes, the binding of a closure can be altered using `#binding`." + } + ], + "Method Objects": [ + { + "question": "What must you first do before invoking an `UnboundMethod` object? ", + "answer": "Bind it to a receiver object using `#bind`." + }, + { + "question": "Are method objects closures? ", + "answer": "No." + }, + { + "question": "How do you obtain a `Method` object from an existing module/class? ", + "answer": "Using `Object#method`" + }, + { + "question": "How do you obtain an `UnboundMethod` object from an existing module/class? ", + "answer": "Using `Module#instance_method`" + } + ], + "Constants": [ + { + "question": "Are constants public or private? ", + "answer": "Public." + }, + { + "question": "What happens if you attempt to define a constant on a class from outside the class? ", + "answer": "It defines successfully since constants are publicly accessible and assignable." + }, + { + "question": "What happens to a constant which is not assigned? ", + "answer": "It will not exist." + } + ], + "Classes": [ + { + "question": "What is the difference between an instance variable and a class variable? ", + "answer": "A class variable is evaluated in reference to the class object created by the enclosing class definition while an instance variable is evaluated in reference to `self`. Instance variables cannot be referenced outside of instance methods." + }, + { + "question": "Why must a class name begin with a capital letter? ", + "answer": "Because the `class` keyword creates a new constant that refers to the class and constants begin with a capital letter." + }, + { + "question": "Is `#initialize` an instance method or a class method? ", + "answer": "An instance method." + }, + { + "question": "What is the difference between a class variable and a class instance variable? ", + "answer": "Class instance variables are instance variables of a class. Class instance variables cannot be used within instance methods." + }, + { + "question": "What is a singleton? ", + "answer": "A class having only a single instance." + }, + { + "question": "How might you create a singleton? ", + "answer": "By including the `Singleton` module." + }, + { + "question": "Can you define accessor methods for class instance variables? ", + "answer": "Yes, if they are defined as singleton methods of the class." + }, + { + "question": "Can classes be nested? ", + "answer": "Yes." + }, + { + "question": "Is `#initialize` public or private? ", + "answer": "Private by default." + }, + { + "question": "What does `#allocate` do? ", + "answer": "It creates an uninitialized instance of a class." + }, + { + "question": "What is an eigenclass? ", + "answer": "An anonymous class associated with an object. An object's singleton methods are instance methods of its associated eigenclass." + }, + { + "question": "What is the relationship between singleton methods and class methods? ", + "answer": "Class methods are singleton methods of the eigenclass associated with the class object." + }, + { + "question": "What is `Class::new`? ", + "answer": "A class method of the `Class` object which creates new classes." + }, + { + "question": "If `Class` `B` is nested within `Class` `A`, and there exists a class method on `A`, does `Class` `B` then have access to this instance method on `Class` `A`? ", + "answer": "No. Nesting one class within another does not give the inner class any special access to the methods or variables of the outer class." + }, + { + "question": "Are eigenclasses inherited? ", + "answer": "The eigenclasses of an object are inherited from the eigenclasses of the superclass of the class object. An eigenclass of an object instance stands alone and does not inherit from any other classes." + }, + { + "question": "What happens to any return value of `#initialize`? ", + "answer": "It is ignored." + }, + { + "question": "What is a factory method? ", + "answer": "An initialization method that creates specialized instances of a class." + }, + { + "question": "What is the method to run initialization code on copied instances of an object? ", + "answer": "`#initialize_copy`" + }, + { + "question": "Does `#initialize_copy` override `#initialize`? ", + "answer": "No." + }, + { + "question": "What does it mean that `#dup` and `#clone` perform shallow copies? ", + "answer": "The instance variables of the copy are copied by reference rather than by value." + }, + { + "question": "What is the difference between `#dup` and `#clone`? ", + "answer": "`#clone` copies the frozen state of an object and any singleton methods of an object while `#dup` does neither." + } + ], + "Modules": [ + { + "question": "What are two main functions of modules? ", + "answer": "As mixins or as namespaces." + }, + { + "question": "Can a module be subclassed? ", + "answer": "No." + }, + { + "question": "What happens when a class includes a module? ", + "answer": "The instance methods of the module become instance methods of the class." + }, + { + "question": "What happens when an object extends a module? ", + "answer": "The instance methods of the module become singleton methods on the object." + }, + { + "question": "What is the superclass of `Class`? ", + "answer": "`Module`" + }, + { + "question": "Why must module names begin with a capital letter? ", + "answer": "Because the module keyword creates a new constant that refers to the module and constants begin with a capital letter." + }, + { + "question": "How would you check if a module has been included by an object? ", + "answer": "Using `#is_a?` such as with `my_obj.is_a? MyModule`." + }, + { + "question": "What does `#module_function` do? ", + "answer": "Makes class copies of the specified methods and makes instance methods private." + } + ], + "Structs": [ + { + "question": "What is a `Struct` in Ruby? ", + "answer": "A core Ruby class that generates other classes containing accessor methods for the specified fields." + }, + { + "question": "Can methods be added to a `Struct`? ", + "answer": "Yes." + } + ], + "Inheritance": [ + { + "question": "What's the difference between `#is_a?` and `#instance_of?`? ", + "answer": "`#instance_of?` ignores inheritance and any mixed-in modules." + }, + { + "question": "If `#super` is invoked without any arguments, which if any arguments get passed to the superclass method? ", + "answer": "All arguments that were passed to the subclass method will be passed to the superclass method." + }, + { + "question": "Are singleton methods inherited? ", + "answer": "No, since they are not defined by a class and thus are unrelated to the inheritance mechanism." + }, + { + "question": "Are class methods inherited? ", + "answer": "Yes." + }, + { + "question": "Are constants inherited? ", + "answer": "Yes." + }, + { + "question": "Are class variables inherited? ", + "answer": "No. The behavior is different than inheritance. Any alteration of a class variable by a subclass affects that class variable in the superclass and all other subclasses of the superclass." + }, + { + "question": "Why might you want to avoid the use of class variables? ", + "answer": "Their values can be changed at any point in the inheritance chain which can cause unexpected behavior in parent classes or subclasses which use those class variables." + }, + { + "question": "What should you watch out for when subclassing a class that is unknown to you? ", + "answer": "Overriding private methods or overwriting class variables." + }, + { + "question": "How might you prevent a method on a superclass from being inherited by a subclass? ", + "answer": "Override the method on the subclass or `undef` the method in the subclass." + } + ], + "Metaprogramming": [ + { + "question": "Can `#attr_reader` be considered an example of metaprogramming? ", + "answer": "Yes, since it creates getter methods at the time of the enclosing class definition." + }, + { + "question": "How might you access an instance variable of a receiver object from outside the scope of the receiver object? ", + "answer": "With an accessor method or using `#instance_variables_get`, `#instance_eval`, or `binding.eval`." + }, + { + "question": "Which method is invoked when a method is not found? ", + "answer": "`#method_missing`" + }, + { + "question": "How can you open an eigenclass from within its associated class? ", + "answer": "`class << self`" + }, + { + "question": "What is a binding? ", + "answer": "A representation of an object's variable bindings at some moment." + }, + { + "question": "What is Ruby's reflection API? ", + "answer": "A collection of methods mostly defined by `Kernel`, `Object`, and `Module` that allow a program to examine its own state and structure." + }, + { + "question": "Which method is called when a constant is not found? ", + "answer": "`#const_missing`" + }, + { + "question": "`#define_method` accepts how many and of what types of arguments? ", + "answer": "A symbol as the method name and either a block or a `Method` object as the method body." + }, + { + "question": "Can `#eval` accept a block? ", + "answer": "No, `#eval` can only accept a string. `#class_eval` and `#instance_eval` can accept blocks." + }, + { + "question": "How might you obtain a reference to an eigenclass from within its associated class? ", + "answer": "`#singleton_class`, `eigenclass = class << self; self; end`" + }, + { + "question": "How might you alter method visibility from outside a class definition? ", + "answer": "Using `#class_eval`" + }, + { + "question": "What is the difference between `#instance_eval` and `#instance_exec`? ", + "answer": "`#instance_exec` can only accept a block, not a string, and it can accept arguments and pass them to the block, allowing the block to be evaluated in the context of the receiver object with parameters whose values come from the block." + }, + { + "question": "Where do `#class_variable_get` and `#class_variables_set` live in the object model? ", + "answer": "`Module`" + }, + { + "question": "Where do `#instance_variable_get` and `#instance_variable_set` live in the object model? ", + "answer": "`Object`" + }, + { + "question": "Where do `#local_variables` and `#global_variables` live in the object model? ", + "answer": "`Kernel`" + } + ], + "Loading Modules, Files, and Gems": [ + { + "question": "What is `$LOAD_PATH`? ", + "answer": "A global array of strings of the directories to be searched when loading files with the load and require methods. `$LOAD_PATH` is equivalent to `$:`." + }, + { + "question": "What is the difference between `#require` and `#load`? ", + "answer": "`#require` can load binary extensions. `#require` does not require a filename extension. `#require` prevents multiple loads of the same file path. `#load` loads the specified file at the current `$SAFE` level while `#require` loads the specified file with a `$SAFE` level of 0." + }, + { + "question": "Does a file loaded with `#require` or `#load` have access to the local variables of the referencing file? ", + "answer": "No." + }, + { + "question": "What is the difference between `#require` and `#require_relative`? ", + "answer": "`#require_relative` ignores the load path." + }, + { + "question": "What does `#autoload` do? ", + "answer": "Allows lazy-loading of files when a constant assigned to a file is first referenced." + }, + { + "question": "What does `File#expand_path` do? ", + "answer": "Converts a relative path to a fully qualified path." + }, + { + "question": "What method in `Dir` can be used to list the contents of a directory? ", + "answer": "`#entries`, `#foreach`..." + }, + { + "question": "What is an `IO` object? ", + "answer": "An IO object is an instance of class `IO` that can be used for reading or writing binary data to and from a file." + }, + { + "question": "Are RubyGems installation directories included in `$LOAD_PATH`? ", + "answer": "Yes." + }, + { + "question": "If more than one version of a Gem is installed, which version will be used? ", + "answer": "The Gem with the highest version number." + }, + { + "question": "How might you alter the default version of a Gem that will be used? ", + "answer": "Using `Kernel#gem`." + } + ], + "Security": [ + { + "question": "What can you say about objects derived from tainted objects? ", + "answer": "They will also be tainted." + }, + { + "question": "What is the default `$SAFE` level? ", + "answer": "0" + }, + { + "question": "What happens when you attempt to lower the `$SAFE` level? ", + "answer": "The `$SAFE` level cannot be lowered; it can only be raised." + }, + { + "question": "What is the difference between taint and trust? ", + "answer": "Taint is derived from the environment such as the command line, environment variables, files, sockets, etc..., while trust is derived from the `$SAFE` level of the originating code. Untrusted objects are both untrusted and tainted." + } + ], + "Exceptions": [ + { + "question": "What error is raised if a method is passed the wrong number of arguments? ", + "answer": "`ArgumentError`" + }, + { + "question": "What error is raised if method name resolution fails? ", + "answer": "`NoMethodError`" + }, + { + "question": "The superclass of `StandardError` is __. ", + "answer": "`Exception`" + }, + { + "question": "What does the default implementation of `BasicObject#method_missing` do? ", + "answer": "Raises a `NoMethodError`." + }, + { + "question": "What happens if you attempt to redefine `BasicObject#__send__`? ", + "answer": "Ruby issues a warning." + } + ], + "Debugging": [ + { + "question": "What is the difference between `#to_s` and `#inspect`? ", + "answer": "`#inspect` is the same as `#to_s`, except some classes redefine `#inspect` to provide output that is more helpful in debugging." + }, + { + "question": "What is the difference between `#puts` and `#p`? ", + "answer": "`#p` converts objects to strings with the `#inspect` method instead of with `#to_s`." + }, + { + "question": "Which Ruby interpreter option enables debugging? ", + "answer": "`-d` / `--debug`" + }, + { + "question": "What is the global variable for the last exception raised? ", + "answer": "`$ERROR_INFO` equivalent to `$!`" + }, + { + "question": "How can you obtain the current state of the call stack? ", + "answer": "Using `Exception.backtrace` or `Kernel#caller`" + }, + { + "question": "What does `Kernel#__method__` return? ", + "answer": "The name of the currently executing method as a symbol." + }, + { + "question": "What is the synonym of `Kernel#__method__`? ", + "answer": "`Kernel#__callee__`" + } + ], + "The Ruby Environment and the Interpreter": [ + { + "question": "What is the difference between `#puts` and `#print`? ", + "answer": "`#puts` appends a newline to the output." + }, + { + "question": "Which Ruby interpreter option allows running of one-line scripts?", + "answer": "`-e`" + }, + { + "question": "Where do the curly brackets to define a hash literal `{}` exist in the object model? ", + "answer": "It does not exist within the object model - it is a function of the interpreter." + }, + { + "question": "What is the default encoding in MRI? ", + "answer": "UTF-8" + }, + { + "question": "How does Ruby know that a setter method such as `X#[]=` should be called in the expression `x.field = []`? ", + "answer": "It is a syntactical conversion in the interpreter." + }, + { + "question": "What is the global constant to access arguments specified on the command line? ", + "answer": "`ARGV`" + }, + { + "question": "Which interpreter option enables warning about deprecated or problematic code? ", + "answer": "`-w`" + }, + { + "question": "In MRI, which objects are not subject to garbage collection? ", + "answer": "Symbols." + }, + { + "question": "What module in the standard library enables English language alternatives to terse global variables? ", + "answer": "`English`" + } + ] +} diff --git a/asm-talk/examples/rubytrivia/resources/retina_wood.png b/asm-talk/examples/rubytrivia/resources/retina_wood.png new file mode 100644 index 0000000..a919ebc Binary files /dev/null and b/asm-talk/examples/rubytrivia/resources/retina_wood.png differ diff --git a/asm-talk/examples/rubytrivia/resources/swipe.png b/asm-talk/examples/rubytrivia/resources/swipe.png new file mode 100644 index 0000000..2c7515d Binary files /dev/null and b/asm-talk/examples/rubytrivia/resources/swipe.png differ diff --git a/asm-talk/examples/rubytrivia/resources/tap.png b/asm-talk/examples/rubytrivia/resources/tap.png new file mode 100644 index 0000000..670cd82 Binary files /dev/null and b/asm-talk/examples/rubytrivia/resources/tap.png differ diff --git a/asm-talk/examples/rubytrivia/spec/main_spec.rb b/asm-talk/examples/rubytrivia/spec/main_spec.rb new file mode 100644 index 0000000..3c96455 --- /dev/null +++ b/asm-talk/examples/rubytrivia/spec/main_spec.rb @@ -0,0 +1,9 @@ +describe "Application" do + before do + @app = UIApplication.sharedApplication + end + + it "has one window" do + @app.windows.size.should == 1 + end +end diff --git a/asm-talk/examples/rubytrivia/spec/models/trivia_spec.rb b/asm-talk/examples/rubytrivia/spec/models/trivia_spec.rb new file mode 100644 index 0000000..fd5d5dc --- /dev/null +++ b/asm-talk/examples/rubytrivia/spec/models/trivia_spec.rb @@ -0,0 +1,52 @@ +describe "Trivia" do + @trivia = Trivia.new + + it "keeps track of it's current quip" do + @trivia.should.respond_to?(:current_quip) + end + + it "can't have the current quip changeable" do + lambda { @trivia.current_quip = "taco" }. + should.raise(NoMethodError) + end + + it "stores everythinin App::Persistence['trivia']" do + App::Persistence['trivia'].should == @trivia.instance_variable_get("@quips") + end + + it "changes and returns current_quip on next" do + old = @trivia.current_quip + quip = @trivia.next + @trivia.current_quip.should == quip + quip.should.not == old + end + + it "changes and returns current_quip on previous" do + old = @trivia.current_quip + quip = @trivia.previous + @trivia.current_quip.should == quip + quip.should.not == old + + end + + it "current_quip is the same value if you next then previous" do + old = @trivia.current_quip + quip = @trivia.next + @trivia.previous + @trivia.current_quip.should == old + quip.should.not == old + end + + it "lists categories based on the .json keys" do + quips = @trivia.instance_variable_get("@quips") + quips.keys.sort.should == @trivia.categories + end + + it "can download the updated json file from github" do + result = @trivia.perform_update + wait 5.0 do + result.should.not == false + end + end + +end \ No newline at end of file diff --git a/asm-talk/examples/rubytrivia/spec/screens/answer_screen_spec.rb b/asm-talk/examples/rubytrivia/spec/screens/answer_screen_spec.rb new file mode 100644 index 0000000..7abb5e0 --- /dev/null +++ b/asm-talk/examples/rubytrivia/spec/screens/answer_screen_spec.rb @@ -0,0 +1,26 @@ +describe "AnswerScreen" do + tests AnswerScreen + + before do + # Simulate AppDelegate setup of main screen + @screen = AnswerScreen.new modal: true, nav_bar: true, answer: "Test Answer" + end + + it "stores the title" do + AnswerScreen.get_title.should == 'Answer' + end + + it "sets title when instantiated" do + @screen.title.should == 'Answer' + end + + it "has a nav bar" do + @screen.nav_bar?.should == true + end + + it "has theme styles" do + Teacup::Stylesheet[:trivia_stylesheet].should.not == nil + Teacup::Stylesheet[:base_stylesheet].should.not == nil + end + +end \ No newline at end of file diff --git a/asm-talk/examples/rubytrivia/spec/screens/modals/help_screen_spec.rb b/asm-talk/examples/rubytrivia/spec/screens/modals/help_screen_spec.rb new file mode 100644 index 0000000..c42372b --- /dev/null +++ b/asm-talk/examples/rubytrivia/spec/screens/modals/help_screen_spec.rb @@ -0,0 +1,32 @@ +describe "HelpScreen" do + tests HelpScreen + + + before do + # Simulate AppDelegate setup of main screen + @screen = HelpScreen.new modal: true, nav_bar: true + @screen.will_appear + end + + it "should store title" do + HelpScreen.get_title.should == 'Help' + end + + it "should set title when instantiated" do + @screen.title.should == 'Help' + end + + it "should have a nav bar" do + @screen.nav_bar?.should == true + end + + it "should have a left bar button item" do + @screen.navigationItem.leftBarButtonItem.should.not == nil + end + + it "has theme styles" do + Teacup::Stylesheet[:trivia_stylesheet].should.not == nil + Teacup::Stylesheet[:base_stylesheet].should.not == nil + end + +end \ No newline at end of file diff --git a/asm-talk/examples/rubytrivia/spec/screens/question_screen_spec.rb b/asm-talk/examples/rubytrivia/spec/screens/question_screen_spec.rb new file mode 100644 index 0000000..a83297b --- /dev/null +++ b/asm-talk/examples/rubytrivia/spec/screens/question_screen_spec.rb @@ -0,0 +1,32 @@ +describe "QuestionScreen" do + tests QuestionScreen + + # Simulate AppDelegate setup of main screen + @screen = QuestionScreen.new nav_bar: true + @screen.will_appear + + it "stores title" do + QuestionScreen.get_title.should == 'Ruby Trivia' + end + + it "sets title when instantiated" do + @screen.title.should == 'Ruby Trivia' + end + + it "has a nav bar" do + @screen.nav_bar?.should == true + end + + it "has a right bar button item" do + @screen.navigationItem.rightBarButtonItem.should.not == nil + end + + it "has a left bar button item" do + @screen.navigationItem.leftBarButtonItem.should.not == nil + end + + it "has theme styles" do + Teacup::Stylesheet[:trivia_stylesheet].should.not == nil + Teacup::Stylesheet[:base_stylesheet].should.not == nil + end +end \ No newline at end of file diff --git a/asm-talk/examples/totally_tacos/.gitignore b/asm-talk/examples/totally_tacos/.gitignore new file mode 100644 index 0000000..c357662 --- /dev/null +++ b/asm-talk/examples/totally_tacos/.gitignore @@ -0,0 +1,16 @@ +.repl_history +build +tags +app/pixate_code.rb +resources/*.nib +resources/*.momd +resources/*.storyboardc +.DS_Store +nbproject +.redcar +#*# +*~ +*.sw[po] +.eprj +.sass-cache +.idea diff --git a/asm-talk/examples/totally_tacos/Gemfile.lock b/asm-talk/examples/totally_tacos/Gemfile.lock new file mode 100644 index 0000000..c83fbc8 --- /dev/null +++ b/asm-talk/examples/totally_tacos/Gemfile.lock @@ -0,0 +1,13 @@ +GEM + remote: https://rubygems.org/ + specs: + joybox (1.1.1) + rake + rake (10.1.0) + +PLATFORMS + ruby + +DEPENDENCIES + joybox + rake diff --git a/asm-talk/examples/totally_tacos/app/app_delegate.rb b/asm-talk/examples/totally_tacos/app/app_delegate.rb new file mode 100644 index 0000000..2af1af6 --- /dev/null +++ b/asm-talk/examples/totally_tacos/app/app_delegate.rb @@ -0,0 +1,47 @@ +class AppDelegate + + def application(application, didFinishLaunchingWithOptions:launchOptions) + + @director = Joybox::Configuration.setup do + director display_stats: true + end + + @navigation_controller = UINavigationController.alloc.initWithRootViewController(@director) + @navigation_controller.navigationBarHidden = true + + @window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds) + @window.setRootViewController(@navigation_controller) + @window.makeKeyAndVisible + + @director << GameLayer.scene + true + end + + def applicationWillResignActive(app) + @director.pause if @navigation_controller.visibleViewController == @director + end + + def applicationDidBecomeActive(app) + @director.resume if @navigation_controller.visibleViewController == @director + end + + def applicationDidEnterBackground(app) + @director.stop_animation if @navigation_controller.visibleViewController == @director + end + + def applicationWillEnterForeground(app) + @director.start_animation if @navigation_controller.visibleViewController == @director + end + + def applicationWillTerminate(app) + @director.end + end + + def applicationDidReceiveMemoryWarning(app) + @director.purge_cached_data + end + + def applicationSignificantTimeChange(app) + @director.set_next_delta_time_zero true + end +end \ No newline at end of file diff --git a/asm-talk/examples/totally_tacos/app/game_layer.rb b/asm-talk/examples/totally_tacos/app/game_layer.rb new file mode 100644 index 0000000..fbfe190 --- /dev/null +++ b/asm-talk/examples/totally_tacos/app/game_layer.rb @@ -0,0 +1,114 @@ +class GameLayer < Joybox::Core::Layer + + @max_tacos = 0 + @cur_size = 1.0 + + scene + + def on_enter + SimpleAudioEngine.sharedEngine.playBackgroundMusic "MexicanFiesta.mp3" + + background = Sprite.new file_name: 'background.png', position: Screen.center + self << background + + @face = Sprite.new file_name: 'normal.png', position: Screen.center, alive: true + @face.run_action Fade.out + self << @face + + show_menu + end + + def show_menu + p "Menu shown" + MenuLabel.default_font_size = 60 + + start_label = MenuLabel.new text: "Start Game", color: '#000000'.to_color, do |menu_item| + start_game + end + + @menu = Menu.new items: [start_label], position: [Screen.half_width, Screen.half_height] + @menu.align_items_vertically + self.add_child(@menu, z: 1) + end + + def start_game + p "Game Start" + + @cur_size = 1.0 + @max_tacos = 10 + @menu.run_action Visibility.hide + @face.run_action Fade.in + @face.position = Screen.center + @face.scale = @cur_size + @face.rotation = 0 + + on_touches_began do |touches, event| + touch = touches.any_object + @face.run_action Move.to position: touch.location + end + + on_touches_moved do |touches, event| + touch = touches.any_object + @face.position = touch.location + end + + schedule_update do |dt| + launch_tacos + check_for_collisions if @face[:alive] + end + + end + + def lose_game + p "Ya lost" + @max_tacos = 0 + @face.stop_all_actions + @face.run_action Fade.out + @menu.run_action Visibility.show + end + + def launch_tacos + @tacos ||= Array.new + + if @tacos.size <= @max_tacos + missing_tacos = @max_tacos - @tacos.size + + missing_tacos.times do + taco = TacoSprite.new + + move_action = Move.to position: taco.end_position, duration: 4.0 + callback_action = Callback.with do |taco| + @tacos.delete taco + self.removeChild(taco) + end + taco.run_action Rotate.by angle: rand(360), duration: 4.0 + taco.run_action Sequence.with actions: [move_action, callback_action] + + self << taco + @tacos << taco + @face[:alive] = true + @face.file_name = 'normal.png' + end + end + end + + def check_for_collisions + if @face[:alive] + @tacos.each do |taco| + if CGRectIntersectsRect(taco.bounding_box, @face.bounding_box) + + @face[:alive] = false + @cur_size += 1 + @face.file_name = "eat.png" + @face.run_action Wiggle.with times: 5, duration: 2.0 + #@face.run_action Blink.with times: 20, duration: 3.0 + @face.run_action Scale.to scale: @cur_size + + lose_game if @cur_size > 3 + break + end + end #each + end #if + end + +end \ No newline at end of file diff --git a/asm-talk/examples/totally_tacos/app/lib/wiggle.rb b/asm-talk/examples/totally_tacos/app/lib/wiggle.rb new file mode 100644 index 0000000..df31df2 --- /dev/null +++ b/asm-talk/examples/totally_tacos/app/lib/wiggle.rb @@ -0,0 +1,37 @@ +# Adding small amounts of madness to joybox stuff +module Joybox + module Actions + class Wiggle + def self.defaults + { + duration: 3.0, + count: 5, + angle: 180 + } + end + + def self.with(options = {}) + options = options.nil? ? defaults : defaults.merge!(options) + #minimum 2 + count = options[:count] < 2 ? 2 : (options[:count]) + wiggle_set = [] + half_rotation = options[:angle] / 2 + per_rotate = options[:duration] / count + + # Get the wiggles + # Half wiggle to start + direction = -1 + wiggle_set << Rotate.by(angle: half_rotation * direction, duration: per_rotate) + # Wiggle loop + (2...count).each do |i| + direction *= -1 + wiggle_set << Rotate.by(angle: options[:angle] * direction, duration: per_rotate) + end + # Half wiggle to end + direction *= -1 + wiggle_set << Rotate.by(angle: half_rotation * direction, duration: per_rotate) + Sequence.with actions: wiggle_set + end + end + end +end \ No newline at end of file diff --git a/asm-talk/examples/totally_tacos/app/taco_sprite.rb b/asm-talk/examples/totally_tacos/app/taco_sprite.rb new file mode 100644 index 0000000..ef3ff23 --- /dev/null +++ b/asm-talk/examples/totally_tacos/app/taco_sprite.rb @@ -0,0 +1,46 @@ +class TacoSprite < Joybox::Core::Sprite + + attr_accessor :end_position + + MaximumSize = 96.0 + + def initialize + @random = Random.new + + kind = @random.rand(1..4) + file_name = "taco_#{kind}.png" + + screen_side = @random.rand(1..4) + start_position = initial_position(screen_side) + @end_position = final_position(screen_side) + + super file_name: file_name, position: start_position + end + + def initial_position(screen_side) + case screen_side + when 1 + [-MaximumSize, @random.rand(1..Screen.height)] + when 2 + [@random.rand(1..Screen.width), Screen.height + MaximumSize] + when 3 + [Screen.width + MaximumSize, @random.rand(1..Screen.height)] + else + [@random.rand(1..Screen.width), -MaximumSize] + end + end + + def final_position(screen_side) + case screen_side + when 1 + [Screen.width + MaximumSize, @random.rand(1..Screen.height)] + when 2 + [@random.rand(1..Screen.width), -MaximumSize] + when 3 + [-MaximumSize, @random.rand(1..Screen.height)] + else + [@random.rand(1..Screen.width), Screen.height + MaximumSize] + end + end + +end \ No newline at end of file diff --git a/asm-talk/examples/totally_tacos/resources/Default-568h@2x.png b/asm-talk/examples/totally_tacos/resources/Default-568h@2x.png new file mode 100644 index 0000000..0f9e292 Binary files /dev/null and b/asm-talk/examples/totally_tacos/resources/Default-568h@2x.png differ diff --git a/asm-talk/examples/totally_tacos/resources/MexicanFiesta.mp3 b/asm-talk/examples/totally_tacos/resources/MexicanFiesta.mp3 new file mode 100644 index 0000000..ed1c1b6 Binary files /dev/null and b/asm-talk/examples/totally_tacos/resources/MexicanFiesta.mp3 differ diff --git a/asm-talk/examples/totally_tacos/resources/background-ipadhd.png b/asm-talk/examples/totally_tacos/resources/background-ipadhd.png new file mode 100644 index 0000000..b925633 Binary files /dev/null and b/asm-talk/examples/totally_tacos/resources/background-ipadhd.png differ diff --git a/asm-talk/examples/totally_tacos/resources/background.png b/asm-talk/examples/totally_tacos/resources/background.png new file mode 100644 index 0000000..c867c89 Binary files /dev/null and b/asm-talk/examples/totally_tacos/resources/background.png differ diff --git a/asm-talk/examples/totally_tacos/resources/eat-ipadhd.png b/asm-talk/examples/totally_tacos/resources/eat-ipadhd.png new file mode 100644 index 0000000..99b0457 Binary files /dev/null and b/asm-talk/examples/totally_tacos/resources/eat-ipadhd.png differ diff --git a/asm-talk/examples/totally_tacos/resources/eat.png b/asm-talk/examples/totally_tacos/resources/eat.png new file mode 100644 index 0000000..a0b97d6 Binary files /dev/null and b/asm-talk/examples/totally_tacos/resources/eat.png differ diff --git a/asm-talk/examples/totally_tacos/resources/fps_images-hd.png b/asm-talk/examples/totally_tacos/resources/fps_images-hd.png new file mode 100644 index 0000000..df86329 Binary files /dev/null and b/asm-talk/examples/totally_tacos/resources/fps_images-hd.png differ diff --git a/asm-talk/examples/totally_tacos/resources/fps_images-ipadhd.png b/asm-talk/examples/totally_tacos/resources/fps_images-ipadhd.png new file mode 100644 index 0000000..df86329 Binary files /dev/null and b/asm-talk/examples/totally_tacos/resources/fps_images-ipadhd.png differ diff --git a/asm-talk/examples/totally_tacos/resources/fps_images.png b/asm-talk/examples/totally_tacos/resources/fps_images.png new file mode 100755 index 0000000..38fc368 Binary files /dev/null and b/asm-talk/examples/totally_tacos/resources/fps_images.png differ diff --git a/asm-talk/examples/totally_tacos/resources/full_eat-ipadhd.png b/asm-talk/examples/totally_tacos/resources/full_eat-ipadhd.png new file mode 100644 index 0000000..475b9b4 Binary files /dev/null and b/asm-talk/examples/totally_tacos/resources/full_eat-ipadhd.png differ diff --git a/asm-talk/examples/totally_tacos/resources/icon.png b/asm-talk/examples/totally_tacos/resources/icon.png new file mode 100644 index 0000000..652fe88 Binary files /dev/null and b/asm-talk/examples/totally_tacos/resources/icon.png differ diff --git a/asm-talk/examples/totally_tacos/resources/icon@2x.png b/asm-talk/examples/totally_tacos/resources/icon@2x.png new file mode 100644 index 0000000..652fe88 Binary files /dev/null and b/asm-talk/examples/totally_tacos/resources/icon@2x.png differ diff --git a/asm-talk/examples/totally_tacos/resources/normal-ipadhd.png b/asm-talk/examples/totally_tacos/resources/normal-ipadhd.png new file mode 100644 index 0000000..4aad105 Binary files /dev/null and b/asm-talk/examples/totally_tacos/resources/normal-ipadhd.png differ diff --git a/asm-talk/examples/totally_tacos/resources/normal.png b/asm-talk/examples/totally_tacos/resources/normal.png new file mode 100644 index 0000000..8c96958 Binary files /dev/null and b/asm-talk/examples/totally_tacos/resources/normal.png differ diff --git a/asm-talk/examples/totally_tacos/resources/taco_1-ipadhd.png b/asm-talk/examples/totally_tacos/resources/taco_1-ipadhd.png new file mode 100644 index 0000000..d2559cd Binary files /dev/null and b/asm-talk/examples/totally_tacos/resources/taco_1-ipadhd.png differ diff --git a/asm-talk/examples/totally_tacos/resources/taco_1.png b/asm-talk/examples/totally_tacos/resources/taco_1.png new file mode 100644 index 0000000..8a2c9fd Binary files /dev/null and b/asm-talk/examples/totally_tacos/resources/taco_1.png differ diff --git a/asm-talk/examples/totally_tacos/resources/taco_2-ipadhd.png b/asm-talk/examples/totally_tacos/resources/taco_2-ipadhd.png new file mode 100644 index 0000000..3eacf44 Binary files /dev/null and b/asm-talk/examples/totally_tacos/resources/taco_2-ipadhd.png differ diff --git a/asm-talk/examples/totally_tacos/resources/taco_2.png b/asm-talk/examples/totally_tacos/resources/taco_2.png new file mode 100644 index 0000000..57e8873 Binary files /dev/null and b/asm-talk/examples/totally_tacos/resources/taco_2.png differ diff --git a/asm-talk/examples/totally_tacos/resources/taco_3-ipadhqd.png b/asm-talk/examples/totally_tacos/resources/taco_3-ipadhqd.png new file mode 100644 index 0000000..7050a36 Binary files /dev/null and b/asm-talk/examples/totally_tacos/resources/taco_3-ipadhqd.png differ diff --git a/asm-talk/examples/totally_tacos/resources/taco_3.png b/asm-talk/examples/totally_tacos/resources/taco_3.png new file mode 100644 index 0000000..097fe6d Binary files /dev/null and b/asm-talk/examples/totally_tacos/resources/taco_3.png differ diff --git a/asm-talk/examples/totally_tacos/resources/taco_4-ipadhd.png b/asm-talk/examples/totally_tacos/resources/taco_4-ipadhd.png new file mode 100644 index 0000000..1db6a17 Binary files /dev/null and b/asm-talk/examples/totally_tacos/resources/taco_4-ipadhd.png differ diff --git a/asm-talk/examples/totally_tacos/resources/taco_4.png b/asm-talk/examples/totally_tacos/resources/taco_4.png new file mode 100644 index 0000000..4b0a541 Binary files /dev/null and b/asm-talk/examples/totally_tacos/resources/taco_4.png differ diff --git a/asm-talk/examples/totally_tacos/spec/main_spec.rb b/asm-talk/examples/totally_tacos/spec/main_spec.rb new file mode 100644 index 0000000..9041a75 --- /dev/null +++ b/asm-talk/examples/totally_tacos/spec/main_spec.rb @@ -0,0 +1,9 @@ +describe "Application 'asteroids'" do + before do + @app = UIApplication.sharedApplication + end + + it "has one window" do + @app.windows.size.should == 1 + end +end diff --git a/asm-talk/img/ascii-table.gif b/asm-talk/img/ascii-table.gif new file mode 100644 index 0000000..4c8074b Binary files /dev/null and b/asm-talk/img/ascii-table.gif differ diff --git a/asm-talk/img/asm-sbs.jpg b/asm-talk/img/asm-sbs.jpg new file mode 100644 index 0000000..e1d15f4 Binary files /dev/null and b/asm-talk/img/asm-sbs.jpg differ diff --git a/asm-talk/img/bg-intro.png b/asm-talk/img/bg-intro.png new file mode 100644 index 0000000..30ad571 Binary files /dev/null and b/asm-talk/img/bg-intro.png differ diff --git a/asm-talk/img/cpu-alu.png b/asm-talk/img/cpu-alu.png new file mode 100644 index 0000000..f314af8 Binary files /dev/null and b/asm-talk/img/cpu-alu.png differ diff --git a/asm-talk/img/demo-gods.jpg b/asm-talk/img/demo-gods.jpg new file mode 100644 index 0000000..d03f4e0 Binary files /dev/null and b/asm-talk/img/demo-gods.jpg differ diff --git a/asm-talk/img/fib-diag.svg b/asm-talk/img/fib-diag.svg new file mode 100644 index 0000000..f832a3e --- /dev/null +++ b/asm-talk/img/fib-diag.svg @@ -0,0 +1,611 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5×5 + 8×8 + 13×13 + 21×21 + + + + + + + + + + + + diff --git a/asm-talk/img/hackernews.png b/asm-talk/img/hackernews.png new file mode 100644 index 0000000..0b4385b Binary files /dev/null and b/asm-talk/img/hackernews.png differ diff --git a/asm-talk/img/me.jpeg b/asm-talk/img/me.jpeg new file mode 100644 index 0000000..77d1872 Binary files /dev/null and b/asm-talk/img/me.jpeg differ diff --git a/asm-talk/img/mem-layout.jpg b/asm-talk/img/mem-layout.jpg new file mode 100644 index 0000000..8c11281 Binary files /dev/null and b/asm-talk/img/mem-layout.jpg differ diff --git a/asm-talk/img/memory-hierarchy.png b/asm-talk/img/memory-hierarchy.png new file mode 100644 index 0000000..0404e0e Binary files /dev/null and b/asm-talk/img/memory-hierarchy.png differ diff --git a/asm-talk/img/one-does-not.jpg b/asm-talk/img/one-does-not.jpg new file mode 100644 index 0000000..c6dd2cf Binary files /dev/null and b/asm-talk/img/one-does-not.jpg differ diff --git a/asm-talk/img/pareto-principle.png b/asm-talk/img/pareto-principle.png new file mode 100644 index 0000000..d0c2226 Binary files /dev/null and b/asm-talk/img/pareto-principle.png differ diff --git a/asm-talk/img/pro-asm.jpg b/asm-talk/img/pro-asm.jpg new file mode 100644 index 0000000..9f1520a Binary files /dev/null and b/asm-talk/img/pro-asm.jpg differ diff --git a/asm-talk/img/starting-line.jpg b/asm-talk/img/starting-line.jpg new file mode 100644 index 0000000..3e085f5 Binary files /dev/null and b/asm-talk/img/starting-line.jpg differ diff --git a/asm-talk/img/toolchain.png b/asm-talk/img/toolchain.png new file mode 100644 index 0000000..5b1ed20 Binary files /dev/null and b/asm-talk/img/toolchain.png differ diff --git a/asm-talk/img/toolchain2.xml b/asm-talk/img/toolchain2.xml new file mode 100644 index 0000000..e54ea32 --- /dev/null +++ b/asm-talk/img/toolchain2.xml @@ -0,0 +1 @@ +7VhNc5swEP01zCSHeEAYjI/+Snpop51xZ3oWILAaGVEhx05/fSWQAAF2PLWTtpn6YnklraT33q60ttzF9vDAYL75RGNELGDHB8tdWgA4jmOLL2l5riyTqV8ZUoZjNagxrPFPpIxqXrrDMSqMgZxSwnFuGiOaZSjihg0yRvfmsIQSc9UcpqhnWEeQ9K3fcMw3lTUAk8b+AeF0o1d2/GnVE8LoMWV0l6n1LOAm5afq3kLtSx202MCY7lsmd2W5C0Ypr1rbwwIRia2GrZp3f6S33jdDGT9ngjrQEyQ7pHdc7os/ayzK0yA53rbc+X6DOVrnMJK9e8G+sG34lohfjmgmmJAFJZSVc8XZkR9Fwl5wRh9RqyeeTENbOuzvWB3iCTGODi2TOsEDolvE2bMYonunCk2lNg3uvqHO9ZVt06JtomxQqSWtPTeIiYYCbRhA8DKAguNcNhOCDjMpTnFqlMWquYwILAocncQxhihIomqeFiTw/Mqgwgd4I38iGVL9zhgMAe9HAQqTU8Cj2AiOPuwtXL0BWLWNIQI5fjJDaghrtcIXisVOalbdicmqY3foKuiORUjNamv8BUdg2nHEIUsR7zkqqa+PfZYaHG9ADj7hkogcZoYu/B87GeXzhGb8rig5nIkBTpAfSnZ0v2il8ntWFGgbEsS0x5Bd5O8GFrfalThXtb+qqydhEYjcFChDYgkYlgNkGOcSvRJPb255S2GBBKeZ1LfQl9i0O5cBjUWOnamOLY5jOX9OYIjIvM6cLbEuZ6vgfqEOpXTuBPUOeymivhHUzppE29Y5OJlN7uyR402ml2lYD6FJUqBLVTV+j0nadd4wS/fD8nP4XT4cgH2PBYbAvklw6Izo7RnSN2HKaIY6mCrT+QEwxJfJaLWmTv2OGREuuA5F9fNLUzRwkdZ0DGX8SyjyexSty/zepaj4T1GbogGGpq/EUPAe0hCwTQD9t0xD0x6CqwOKdtVt1eh8JPxIrV9F6W1k/z25gw5bQ09795X0rpXxjt/2oqwu377K5A6T8Wfe++Nrvfe9V3zvuz2JfJUh+nfeUEeib0AoRwPS9TrYBv2AHA9oBFwjHvtPBF2/yNRzdjHUq4Q+4uzRLKtUhUTidoVULaIrpO7gMzh/45rpKN3n1EgvyKAbq6dux+EodUwH5vTfKZvEz+Z/s2p48+eku/oF \ No newline at end of file diff --git a/asm-talk/img/trump.jpg b/asm-talk/img/trump.jpg new file mode 100644 index 0000000..3590e97 Binary files /dev/null and b/asm-talk/img/trump.jpg differ diff --git a/asm-talk/img/von-neumann.gif b/asm-talk/img/von-neumann.gif new file mode 100644 index 0000000..c6fc99b Binary files /dev/null and b/asm-talk/img/von-neumann.gif differ diff --git a/asm-talk/img/wat.jpg b/asm-talk/img/wat.jpg new file mode 100644 index 0000000..f87df02 Binary files /dev/null and b/asm-talk/img/wat.jpg differ diff --git a/asm-talk/img/x86-registers.png b/asm-talk/img/x86-registers.png new file mode 100644 index 0000000..8eecfb8 Binary files /dev/null and b/asm-talk/img/x86-registers.png differ diff --git a/asm-talk/index-pdf.html b/asm-talk/index-pdf.html new file mode 100644 index 0000000..b480b7a --- /dev/null +++ b/asm-talk/index-pdf.html @@ -0,0 +1,1437 @@ + + + + + + + Will van Ketwich - Fibonacci Assembly Slides + + + + + + + + + + + + + + + + +
+ + +
+
+
+

Creating a Fibonacci Generator in Assembly

+ + + +

Because ¯\_(ツ)_/¯

+

By Will van Ketwich

+ + +
+ +
+

@wilvk

+

+ Just a dude that does stuff... mostly with computers. +

+

+ +

+

+ Systems Engineer at REA Group
+ Group Delivery Engineering, Group Technology
+

+
+ +
+ +
+
+

Assembly

+

+ +

+ +
+ +
+

Why???

+
+

Seriously dude, why Assembly?

+
+
+
+

+ + + + + +
+
  • The building blocks of all languages +
  • How processes work +
  • How to reverse engineer +
  • How the Linux Kernel works +
  • How device drivers work +
  • Improve troubleshooting skills +
  • Curiosity +
  • + +
    +

    +
    + + +
    + +
    +

    How?

    +

    How to get started?

    +
    + + + + + + +
    +
  • Read a few books +
  • Do some examples +
  • Define a project +
  • Look online for help +
  • + + + +
    + +
    +
    + +
    + +
    +

    A Small Project

    +
    +
    +
      +
    1. Reading input from the command line +
    2. Get length of command line argument +
    3. Converting input to a number +
    4. Generating the Fibonacci number +
    5. Printing the output to screen +
    +
    +
    +
    
    +            $ ./fib7 46
    +            2971215073
    +          
    +
    + +
    + +
    +

    Decisions to be made

    +
    +
    +
  • Should standard libraries be used? (glibc)
    +
  • What flavour of assembly to use?
    NASM, GAS, MASM, YASM?
    +
  • 64 bit or 32 bit? +
  • + +
    + +
    + +
    + +
    +

    The Fibonacci Sequence

    + + +
    + +
    +

    The Fibonacci Algorithm

    +
    +

    From Wikipedia:

    +
    +
    +

    + The sequence Fn of Fibonacci numbers is defined by the recurrence relation: +

    +

    +
    + Fn=Fn-1 + Fn-2 +

    +

    +
    + with seed values: +

    +

    +
    + F1=1, F2=1 +

    +

    +
    + or: +

    +

    +
    + F0=0, F1=1 +

    +
    + +
    + +
    +

    A resultant sequence

    +
    +
    +
    +

    + + + + + + + + + + + + + + + + +
    Value011235813213455...
    +
    + + + + + + + + + + + + + + + + +
    Position--123456789...
    +
    +

    +
    +
    +

    The Fibonacci Algorithm

    +

    As C code

    +
    +
    
    +int fib(int n)
    +{
    +  int f[n+2];
    +  int i;
    +  f[0] = 0;
    +  f[1] = 1;
    +
    +  for (i = 2; i <= n; i++)
    +  {
    +    f[i] = f[i-1] + f[i-2];
    +  }
    +  return f[n];
    +}
    +          
    + +

    + +
    +
    + +
    +

    Beginning our implementation

    +

    And some starting knowledge

    + +
    + +
    +

    GAS Files and Language Syntax

    +

    fib1.s - doing nothing takes something

    +
    +
    
    +.section .text
    +.globl _start
    +_start:
    +    nop
    +    # the rest of our program goes here
    +    movl $1, %eax
    +    movl $0, %ebx
    +    int $0x80
    +          
    +
    + +
    +

    The building blocks

    +

    Opcodes and Operands

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    LineOpcodeOperand 1Operand 2Description
    nopnop--no-operation
    movl $1, %eaxmovl$1%eaxcopy 1 into register eax
    movl $0, %ebxmovl$0%ebxcopy 0 into register ebx
    int $0x80int$0x80-call interrupt number 0x80
    + +
    + +
    +

    The tools of the trade

    +

    Assemblers and Linkers

    + + + + + +
    + + +
    
    +
    +as --32 -gstabs -o fib1.o fib1.s
    +
    +
    +ld -m elf_i386 -o fib1 fib1.o
    +
    +                
    +
    + + +
    + +
    +

    The tools of the trade

    +

    Object file utilities

    +
    +
  • nm - lists the symbols from object files +
  • objdump - displays more information about object files +
  • elfdump - similar to objdump +
  • gdb - GNU debugger +
  • gcc - GNU compiler collection +
  • make - used for build toolchains +
  • + +
    + +
    +

    The canvas

    +

    CPU and Registers

    + +
    +
    + +
    +

    The canvas

    +

    Memory Hierarchy

    + +
    +
    + +
    +

    The canvas

    +

    Registers

    + +
    +
    + +
    +

    NOP

    +
    +
    +
  • Does nothing functional +
  • Takes up a clock cycle +
  • Can be used to fill space +
  • +
    +
    
    +nop
    +          
    +
    + +
    +

    MOV

    +
    +
    +
  • MOVes (or copies) data from one location to another +
  • Can copy to/from memory, register and immediates +
  • Cannot copy from memory to memory +
    +
    + Some examples: +
    +
    
    +mov (%ebx), %eax # copy address pointed to by ebx to register eax
    +mov %ebx, (%eax) # copy value in ebx to address pointed to by eax
    +mov $1, %eax     # place value 1 into register eax
    +mov $5, (%eax)   # place value 5 into address pointed to by eax
    +mov %ebp, %esp   # copy value in register ebp into register esp
    +          
    +
  • +
    +
    +

    MOV - Operation Suffixes

    +
    +
  • Different variations based on size to copy +
  • Used for many instructions (MOVL, PUSHL, POPL, etc.) +
  • Floating point versions used with the FPU and SIMD +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    SuffixTypeBits (Integer)Bits (Floating Point)
    bbyte8-
    sshort1632
    wword16-
    llong3264
    qquad64-
    tten bytes-80
    +
    +
    + Some examples: +
    
    +movb $2, (%ebx)  # moves 0x02 into ebx
    +movw $2, (%ebx)  # moves 0x0002 into ebx
    +movl $2, (%ebx)  # moves 0x00000002 into ebx
    +          
    +
  • +
    + +
    +

    INT

    +
    +
  • Interrupts the CPU from scheduled processing +
  • Most interrupts are hardware-based +
  • Software-based interrupts are called 'soft-interrupts' +
  • Requesting actions from User Space in Kernel Space +
      +
    • Linux uses INT 0x80 +
    • MacOS uses INT 0x60 +
    • Windows uses INT 0x21 +
    +
    
    +# exit with return code 0
    +movl $1, %eax
    +movl $0, %ebx
    +int 0x80
    +          
    +
  • Modern CPUs/OSes use SYSCALL but INT is still valid +
  • +
    + +
    + +
    + +
    +

    1. Reading input from the
    command line

    +
    +
      +
    1. Reading input from the command line +
    2. Get length of command line argument +
    3. Converting input to a number +
    4. Generating the Fibonacci number +
    5. Printing the output to screen +
    +
    +
    +

    Memory Layout

    + +
    +
    +

    Command Line Arguments in the Stack

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    StackData
    ...
    ESP + n+8< pointer to second environment variable >
    ESP + n+4< pointer to first environment variable >
    ESP + n< NULL for end of command line arguments >
    ESP + n-4< pointer to last string argument >
    ...
    ESP + 12< pointer to second string argument >
    ESP + 8< pointer to a string that contains the first argument >
    ESP + 4< pointer to a string containing the name of the application >
    ESP + 0< number of arguments on command line >
    ...
    +
    + +
    +

    A Simple Print Utility

    +

    fib2.s

    +
    +
    
    +# stack args example
    +.section .text
    +.globl _start
    +  _start:
    +
    +    nop
    +    movl %esp, %ebp     # take a copy of the stack pointer esp into ebp
    +    addl $8, %ebp       # address of first arg in stack
    +    movl (%ebp), %ecx   # move the address of the first arg into ecx
    +
    +    movl $4, %edx       # set the length of our string to 4
    +    movl $4, %eax       # indicate to int 0x80 that we are doing a write
    +    movl $0, %ebx       # indicate to int 0x80 that we are writing to file descriptor 0
    +    int $0x80           # call int 0x80 for write
    +
    +    movl $1, %eax       # exit gracefully
    +    movl $0, %ebx       # with return code 0
    +    int $0x80           # call int 0x80 for exit
    +          
    +
    +
    +

    Viewing the Stack in GDB

    +

    A demo

    +
    + + +
    + + +
    +
    + +
    +

    2. Get length of command line argument

    +
    +
      +
    1. Reading input from the command line +
    2. Get length of command line argument +
    3. Converting input to a number +
    4. Generating the Fibonacci number +
    5. Printing the output to screen +
    +
    +
    +

    Approach

    +
    +
    +
  • Find address of first command line argument string +
  • Get length of string +
  • Print string to stdout +
  • +
    +
    +

    Source

    +

    fib3.s

    +
    
    +# framework - get first argument from the command line and print to stdout
    +.section .text
    +.globl _start
    +_start:
    +    nop
    +    movl %esp, %ebp     # take a copy of esp to use
    +    addl $8, %ebp       # address of first arg in stack
    +    movl (%ebp), %edi   # move arg address into esi for scasb
    +    push %edi           # store the string address as edi gets clobbered
    +
    +    movl $50, %ecx      # set ecx counter to a high value
    +    movl $0, %eax       # zero al search char
    +    movl %ecx, %ebx     # copy our max counter value to edx
    +    cld                 # set direction down
    +    repne scasb         # iterate until we find the al char
    +
    +    subl %ecx, %ebx     # subtract from our original ecx value
    +    dec %ebx            # remove null byte at the end of the string from the count
    +    pop %ecx            # restore our string address into ecx
    +    mov %ebx, %edx      # move our count value to edx for the int 80 call
    +
    +    movl $4, %eax       # set eax to 4 for int 80 to write to file
    +    movl $0, %ebx       # set ebx for file to write to as stdoout (file descriptor 0)
    +    int $0x80           # make it so
    +    movl $1, %eax       # set eax for int 80 for system exit
    +    movl $0, %ebx       # set ebx for return code 0
    +    int $0x80           # make it so again
    +          
    +
    +
    +

    Source

    +

    New Code

    +
    +
    
    +    movl (%ebp), %edi   # move arg address into esi for scasb
    +    push %edi           # store the string address as edi gets clobbered
    +
    +    movl $50, %ecx      # set ecx counter to a high value
    +    movl $0, %eax       # zero al search char
    +    movl %ecx, %ebx     # copy our max counter value to edx
    +    cld                 # set direction down
    +    repne scasb         # iterate until we find the al char
    +
    +    subl %ecx, %ebx     # subtract from our original ecx value
    +    dec %ebx            # remove null byte at the end of the string from the count
    +    pop %ecx            # restore our string address into ecx
    +    mov %ebx, %edx      # move our count value to edx for the int 80 call
    +          
    +
    + +
    +

    repne scasb

    +

    Scanning Strings

    +
    +
    +
  • edi - points to address of string to scan +
  • al - stores the byte to scan until +
  • ecx - stores the result of the scan count +
    +
    +
  • requires registers set up before running (like INT) +
    +
    +
  • the cld opcode clears the direction flag +
  • each iteration increases edi and decreases ecx +
  • +
    +
    +

    Some Arithmetic

    +
    +
    + + + + + + + + + + + + + +
    + ecx = 50 - ( len(string) + 1 ) +
    +
    + but we want len(string) +
    +
    +
    + len(string) + 1 = 50 - ecx +
    +
    + len(string) = (50 - ecx) - 1 +
    +
    +
    +
    +
    
    +subl %ecx, %ebx     # subtract from our original ecx value
    +dec %ebx            # remove null byte at the end of the string from the count
    +          
    + +
    +
    +

    Labels, CALL, RET and the Stack

    +

    labels

    +
    +
    +
  • points to an addresses in memory +
  • label addresses resolved with ld +
    +
    +
    + Standard labels: +
    my_function:
    +
    +
    + Local labels: +
    .my_local_function:
    +
  • +
    + +
    +

    Labels, CALL, RET and the Stack

    +

    CALL and RET

    +
    +
    + CALL: +
    +
  • places next instruction address on the stack +
  • jumps execution to address of label +
    +
    + RET: +
    +
  • RET jumps execution back to the next address on the stack +
  • functions are just a logical placing of CALL and RET +
  • no set order to location of labels +
  • +
    +
    +

    Functions

    +

    A Simple Example

    +
    +
    +
    
    +          call get_string_length
    +          mov %eax, %ebx
    +
    +          ...
    +
    +          get_string_length:
    +          mov $1, %eax
    +          ret
    +          
    +
    +
    +

    The implementation

    +

    fib4.s

    +
    
    +# framework - refactor into separate functions
    +.section .text
    +.globl _start
    +
    +# entrypoint of application
    +_start:
    +    nop
    +    movl %esp, %ebp     # take a copy of esp to use
    +    addl $8, %ebp       # address of first arg in stack
    +    movl (%ebp), %edi   # move arg address into esi for scasb
    +    push %edi           # store the string address as edi gets clobbered
    +    call get_string_length
    +    pop %ecx            # restore our string address into ecx
    +    call print_string
    +    call exit
    +
    +# get length of string pointed to by edi and place result in ebx
    +get_string_length:
    +    movl $50, %ecx      # set ecx counter to a high value
    +    movl $0, %eax       # zero al search char
    +    movl %ecx, %ebx     # copy our max counter value to edx
    +    cld                 # set direction down
    +    repne scasb         # iterate until we find the al char
    +    movl %ecx, %edx     # move count into edx
    +    subl %ecx, %ebx     # subtract from our original ecx value
    +    dec %ebx            # remove null byte at the end of the string from the count
    +    ret
    +
    +# print the string in ecx to the length of ebx
    +print_string:
    +    mov %ebx, %edx      # move our count value to edx for the int 80 call
    +    movl $4, %eax       # set eax to 4 for int 80 to write to file
    +    movl $0, %ebx       # set ebx for file to write to as stdoout (file descriptor 0)
    +    int $0x80           # make it so
    +    ret
    +
    +# exit the application
    +exit:
    +    movl $1, %eax       # set eax for int 80 for system exit
    +    movl $0, %ebx       # set ebx for return code 0
    +    int $0x80           # make it so again
    +          
    +
    + +
    +
    + +
    +

    3. Converting input to a number

    +
    +
      +
    1. Reading input from the command line +
    2. Get length of command line argument +
    3. Converting input to a number +
    4. Generating the Fibonacci number +
    5. Printing the output to screen +
    +
    +
    +

    long_from_string

    +

    As (pseudo) C code

    +
    +
    
    +long long_from_string(*char number_string)
    +{
    +  int i=0;
    +  long return_value=0;
    +  int temp_value=0;
    +  char digit = number_string[i];
    +
    +  while(digit >= ‘0’ && digit <= ‘9’)
    +  {
    +    temp_value = digit - 48;
    +    return_value *= 10;
    +    return_value += temp_value;
    +    digit = number_string[++i];
    +  }
    +
    +  return return_value;
    +}
    +          
    +
    + +
    +

    long_from_string

    +

    fib5.s

    +
    
    +long_from_string:
    +    xor %eax, %eax # set eax as our result register
    +    xor %ecx, %ecx # set ecx(cl) as our temporary byte register
    +.top:
    +    movb (%edi), %cl
    +    inc %edi
    +    cmpb $48, %cl  # check if value in ecx is less than ascii '0'. exit if less
    +    jl .done
    +    cmpb $57, %cl  # check if value in ecx is greater than ascii '9'. exit if greater
    +    jg .done
    +    sub $48, %cl
    +    imul $10, %eax
    +    add %ecx, %eax
    +    jmp .top
    +.done:
    +    ret
    +          
    +
    + +
    +

    ASCII

    + +
    + +
    +

    Compare and Jump Opcodes

    +
    +
    +
  • CMP compares two values and sets flags based on the result +
  • Flags include carry, zero, overflow/underflow +
  • The flags are used to jump to a label/address +
    +
    Many types of jump flags: +
  • jg = jump if greater than +
  • jl = jump if less than +
  • je = jump if equal +
  • jge = jump if greater than or equal +
  • jle = Jump if less than or equal +
  • jmp = jump unconditionally +
  • and so on. +
  • +
    + +
    +

    Relevance to Structured Programming

    +
    +
    +
  • Jumps, Compares and Labels +
  • basis of Structured Programming Constructs +
  • counters and comparisons +
    +
    + Can create: +
    +
    +
  • Selection - if..else..then +
  • Iteration - while, repeat, for, do..while +
  • +
    + +
    + +
    +
    +

    4. Generating the Fibonacci Number

    +
    +
      +
    1. Reading input from the command line +
    2. Get length of command line argument +
    3. Converting input to a number +
    4. Generating the Fibonacci number +
    5. Printing the output to screen +
    +
    + +
    +

    The Fibonacci Function

    +

    fib6.s

    +
    
    +# input: eax holds our fibonacci n
    +# processing: iterate the fibonacci sequence n times
    +# output: return our fibonacci result in ebx
    +
    +fibonacci:
    +    pushl %ebp       # preserve ebp
    +    mov %esp, %ebp   # copy the stack pointer to ebp for use
    +    mov %eax, %ebx   # make a cpoy of our fib(n) value for allocating an array on the stack
    +    addl $2, %ebx    # add 2 extra spaces to the array size in case n=1 or n=1
    +    subl %ebx, %esp  # add the size of our array to the stack to allocate the required space
    +    xor %ecx, %ecx   # set our counter to zero
    +    movl %ecx, (%esp, %ecx, 4)  # initialise our array with 0 for esp[0]
    +    incl %ecx                   # increase our counter
    +    movl %ecx, (%esp, %ecx, 4)  # initialise our array with 1 for esp[1]
    +    incl %ecx                   # our counter/iterator should be at 2 now
    +
    +.fib_loop:
    +    cmp %eax, %ecx                # compare our counter (ecx) to n (eax)
    +    jge .fib_done                 # if it's greater or equal, we're done
    +    movl -4(%esp, %ecx, 4), %ebx  # get the value in the stack at esp-1 from our current stack pointer location
    +    movl -8(%esp, %ecx, 4), %edx  # get the value in the stack esp-2 from our current stack pointer location
    +    addl %edx, %ebx               # add the values esp-1 and esp-2 together
    +    movl %ebx, (%esp, %ecx, 4)    # place the result in the current stack location
    +    incl %ecx                     # bump our counter
    +    jmp .fib_loop                 # loop again
    +
    +.fib_done:
    +    movl %ebp, %esp               # move our copy of the stack pointer back to esp
    +    popl %ebp                     # retrieve the original copy of ebp from the stack
    +    ret
    +          
    +
    + +
    +

    Coming back to our C algorithm

    +
    +
    
    +int fib(int n)
    +{
    +  int f[n+2];
    +  int i;
    +  f[0] = 0;
    +  f[1] = 1;
    +
    +  for (i = 2; i <= n; i++)
    +  {
    +    f[i] = f[i-1] + f[i-2];
    +  }
    +  return f[n];
    +}
    +          
    + +
    +
    +

    Creating stack space

    +

    fib6.s

    +
    +
    
    +fibonacci:
    +    pushl %ebp      # preserve ebp
    +    mov %esp, %ebp  # copy the stack pointer to ebp for use
    +
    +    mov %eax, %ebx  # make a cpoy of our fib(n) value for allocating an array on the stack
    +    addl $2, %ebx   # add 2 extra spaces to the array size in case n=1 or n=1
    +    shl $2, %ebx    # multiply by 4 as we are using longs (32 bits)
    +    subl %ebx, %esp # add the size of our array to the stack to allocate the required space
    +
    +    xor %ecx, %ecx              # set our counter to zero
    +    movl %ecx, (%esp, %ecx, 4)  # initialise our array with 0 for esp[0]
    +    incl %ecx                   # increase our counter
    +    movl %ecx, (%esp, %ecx, 4)  # initialise our array with 1 for esp[1]
    +    incl %ecx                   # our counter/iterator should be at 2 now
    +        
    +
    + +
    +

    Saving the stack pointer (esp)

    +

    When modifying ESP in a function

    +
    +
    
    +fibonacci:
    +    pushl %ebp      # preserve ebp as we are going to use it to store our stack pointer for the return call
    +    mov %esp, %ebp  # copy the stack pointer to ebp for use
    +
    +...
    +
    +.fib_done:
    +    movl %ebp, %esp # move our copy of the stack pointer back to esp
    +    popl %ebp       # retrieve the original copy of ebp from the stack
    +    ret
    +          
    +
    + +
    +

    Variable initialisation

    +
    +
    +
  • using longs (32 bit values) +
  • each long is 4 bytes +
    +
    +
  • we shift left twice to multiply by 4 +
    
    +shl $2, %ebx
    +          
    +
    +
  • our stack grows downward, hence subtract for more space +
  • +
    
    +subl %ebx, %esp
    +          
    +
    + +
    +

    Indexed memory MOV formats

    +
    +

    Absolute indexed memory location

    + copy ecx into the memory address esp + ( 4 * ecx) +
    
    +movl %ecx, (%esp, %ecx, 4)
    +          
    +
    +

    Absolute and relative indexed memory

    + copy the memory location at ( esp + ( 4 * ecx) - 4 ) into ebx +
    
    +movl -4(%esp, %ecx, 4), %ebx
    +          
    +
    +

    The general rule is:

    +
    
    +relative_offset(absolute_offset, index, size)
    +          
    +
    + +
    +

    The core of the Fibonacci implementation

    +
    +
    
    +.fib_loop:                        # we begin our for loop here
    +    cmp %eax, %ecx                # compare our counter (ecx) to n (eax) if it's greater or equal, we're done
    +    jge .fib_done
    +    movl -4(%esp, %ecx, 4), %ebx  # get the value in the stack at esp-1 from our current stack pointer location
    +    movl -8(%esp, %ecx, 4), %edx  # get the value in the stack esp-2 from our current stack pointer location
    +    addl %edx, %ebx               # add the values esp-1 and esp-2 together
    +    movl %ebx, (%esp, %ecx, 4)    # place the result in the current stack location
    +    incl %ecx                     # bump our counter
    +    jmp .fib_loop                 # loop again
    +          
    +
    + +
    + +
    + +
    +

    5. Printing the output to screen

    +
    +
      +
    1. Reading input from the command line +
    2. Get length of command line argument +
    3. Converting input to a number +
    4. Generating the Fibonacci number +
    5. Printing the output to screen +
    +
    + +
    +

    print_long

    +

    fib7.s

    +
    
    +print_long:
    +    push %ebp
    +    mov %esp, %ebp              # copy the stack pointer to ebp for use
    +    add $10, %esp               # add 10 to esp to make space for our string
    +    mov $10, %ecx               # set our counter to the end of the stack space allocated (higher)
    +    mov %ebx, %eax              # our value ebx is placed into eax for division
    +.loop_pl:
    +    xor %edx, %edx              # clear edx for the dividend
    +    mov $10, %ebx               # ebx is our divisor so we set it to divide by 10
    +    div %ebx                    # do the division
    +    addb $48, %dl               # convert the quotient to ascii
    +    movb %dl, (%esp, %ecx, 1)   # place the string byte into memory
    +    dec %ecx                    # decrease our counter (as we are working backwards through the number)
    +    cmp $0, %ax                 # exit if the remainder is 0
    +    je .done_pl
    +    jmp .loop_pl                # loop again if necessary
    +.done_pl:
    +    addl %ecx, %esp             # shift our stack pointer up to the start of the buffer
    +    incl %esp                   # add 1 to the stack pointer for the actual first string byte
    +    sub $10, %ecx               # as we are counting down, we subtract 10 from ecx to give the actual number of digits
    +    neg %ecx                    # convert to a positive value
    +    mov %ecx, %edx              # move our count value to edx for the int 80 call
    +    mov %esp, %ecx              # move our string start address into ecx
    +    movl $4, %eax               # set eax to 4 for int 80 to write to file
    +    movl $0, %ebx               # set ebx for file to write to as stdoout (file descriptor 0)
    +    int $0x80                   # make it so
    +    movl %ebp, %esp             # move our copy of the stack pointer back to esp
    +    popl %ebp                   # retrieve the original copy of ebp from the stack
    +    ret
    +          
    +
    +
    +

    Overview

    +

    From comments (for brevity)

    +
    +
    +# allocate space on the stack for 10 characters
    +
    +# start a loop and check if value is zero - jump to done if so
    +
    +# divide the number by 10 and take the remainder as the first digit
    +
    +# add 48 to the number to make it an ascii value
    +
    +# store the byte in the address esp + ecx
    +
    +# jump to start of loop
    +        
    +
  • Essentially the opposite of long_to_string +
  • +
    +

    DIV

    +

    division

    +
    +
    +
  • a / b = y remainder z +
  • dividend / divisor = [ quotient, remainder ] +
  • eax / ebx = [ eax, edx ] +
    +
    +
    
    +...
    +
    +    mov %ebx, %eax              # our value ebx is placed into eax for division
    +.loop_pl:
    +    xor %edx, %edx              # clear edx for the dividend
    +    mov $10, %ebx               # ebx is our divisor so we set it to divide by 10
    +    div %ebx                    # do the division
    +    addb $48, %dl               # convert the quotient to ascii
    +
    +...
    +          
    +
  • +
    +
    +

    NEG

    +

    multiplying by -1

    +
    +
    neg %eax
    +
    +
  • takes two's compliment of number +
  • most significant bit indicates sign +
  • 1 = negative, 0 = positive +
  • number inverted and 1 added to result +
  • loose absolute range (eg. 8 bits holds -128 to 127) +
  • NEG(-12) = 12 +
  • 11110100 -> 00001011 + 1 = 00001100 +
  • +
    +
    +

    Printing to stdout

    +

    and shuffling some registers

    +
    +
    
    +mov %ecx, %edx              # move our count value to edx for the int 80 call
    +mov %esp, %ecx              # move our string start address into ecx
    +movl $4, %eax               # set eax to 4 for int 80 to write to file
    +movl $0, %ebx               # set ebx for file to write to as stdoout (file descriptor 0)
    +int $0x80                   # make it so
    +          
    +
    + +
    +
    +
    +

    Conclusion

    +

    Results and limitations

    +
    +
  • working program +
    
    +_start:
    +    nop
    +    movl %esp, %ebp              # take a copy of esp to use
    +    addl $8, %ebp                # address of first arg in stack
    +    movl (%ebp), %edi            # move arg address into esi for scasb
    +    call get_string_length       # get the length of the argument string passed in
    +    call long_from_string        # get a numeric value from our argument
    +    call check_valid_input       # if the result is zero, exit
    +    call fibonacci               # run our fibonacci sequence
    +    call print_long              # print the last value in the sequence
    +    call exit                    # exit gracefully
    +          
    +
  • no error checking +
  • limited by 32-bit +
  • sub-optimal code +
  • +
    + +
    +

    Conclusion

    +

    Most of the work doing standard library things

    + +
    + +
    +

    Conclusion

    +

    Insight into language composition

    +
    +
    +
  • Jumps are GOTOs +
  • Frowned upon in higher level languages - Djikstra +
  • Fundamental units of operation in any application +
  • +
    + +
    +

    Conclusion

    +

    It was fun!

    +
    + I got some HackerNews rep from a blog post on it! +
    + +
    + +
    +

    Conclusion

    +

    Call to action

    +
    +
    +
  • Learning continuum +
  • Learn as part of something larger +
    +
    + Helps with understanding of: +
  • LLVM +
  • eBPF +
  • GPU Assembly +
  • WebAssembly +
  • +
    + +
    + +
    +
    +

    Thank you!

    +

    + Questions? +

    +

    + @wilvk +

    + +
    +
    + + +
    + +
    + + + + + + + + + diff --git a/asm-talk/index.html b/asm-talk/index.html new file mode 100644 index 0000000..109c91a --- /dev/null +++ b/asm-talk/index.html @@ -0,0 +1,1431 @@ + + + + + + Will van Ketwich - Fibonacci Assembly Slides + + + + + + + + + + + + + + + + +
    + + +
    +
    +
    +

    Creating a Fibonacci Generator in Assembly

    + + + +

    Because ¯\_(ツ)_/¯

    +

    By Will van Ketwich

    + + +
    + +
    +

    @wilvk

    +

    + Just a dude that does stuff... mostly with computers. +

    +

    + +

    +

    + Systems Engineer at REA Group
    + Group Delivery Engineering, Group Technology
    +

    +
    + +
    + +
    +
    +

    Assembly

    +

    + +

    + +
    + +
    +

    Why???

    +
    +

    Seriously dude, why Assembly?

    +
    +
    +
    +

    + + + + + +
    +
  • The building blocks of all languages +
  • How processes work +
  • How to reverse engineer +
  • How the Linux Kernel works +
  • How device drivers work +
  • Improve troubleshooting skills +
  • Curiosity +
  • + +
    +

    +
    + + +
    + +
    +

    How?

    +

    How to get started?

    +
    + + + + + + +
    +
  • Read a few books +
  • Do some examples +
  • Define a project +
  • Look online for help +
  • + + + +
    + +
    +
    + +
    + +
    +

    A Small Project

    +
    +
    +
      +
    1. Reading input from the command line +
    2. Get length of command line argument +
    3. Converting input to a number +
    4. Generating the Fibonacci number +
    5. Printing the output to screen +
    +
    +
    +
    
    +            $ ./fib7 46
    +            2971215073
    +          
    +
    + +
    + +
    +

    Decisions to be made

    +
    +
    +
  • Should standard libraries be used? (glibc)
    +
  • What flavour of assembly to use?
    NASM, GAS, MASM, YASM?
    +
  • 64 bit or 32 bit? +
  • + +
    + +
    + +
    + +
    +

    The Fibonacci Sequence

    + + +
    + +
    +

    The Fibonacci Algorithm

    +
    +

    From Wikipedia:

    +
    +
    +

    + The sequence Fn of Fibonacci numbers is defined by the recurrence relation: +

    +

    +
    + Fn=Fn-1 + Fn-2 +

    +

    +
    + with seed values: +

    +

    +
    + F1=1, F2=1 +

    +

    +
    + or: +

    +

    +
    + F0=0, F1=1 +

    +
    + +
    +
    +

    A resultant sequence

    +
    +
    +
    +

    + + + + + + + + + + + + + + + + +
    Value011235813213455...
    +
    + + + + + + + + + + + + + + + + +
    Position--123456789...
    +
    +

    +
    +
    +

    The Fibonacci Algorithm

    +

    As C code

    +
    +
    
    +int fib(int n)
    +{
    +  int f[n+2];
    +  int i;
    +  f[0] = 0;
    +  f[1] = 1;
    +
    +  for (i = 2; i <= n; i++)
    +  {
    +    f[i] = f[i-1] + f[i-2];
    +  }
    +  return f[n];
    +}
    +          
    + +

    + +
    + +
    + +
    +

    Beginning our implementation

    +

    And some starting knowledge

    + +
    + +
    +

    GAS Files and Language Syntax

    +

    fib1.s - doing nothing takes something

    +
    +
    
    +.section .text
    +.globl _start
    +_start:
    +    nop
    +    # the rest of our program goes here
    +    movl $1, %eax
    +    movl $0, %ebx
    +    int $0x80
    +          
    +
    + +
    +

    The building blocks

    +

    Opcodes and Operands

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    LineOpcodeOperand 1Operand 2Description
    nopnop--no-operation
    movl $1, %eaxmovl$1%eaxcopy 1 into register eax
    movl $0, %ebxmovl$0%ebxcopy 0 into register ebx
    int $0x80int$0x80-call interrupt number 0x80
    + +
    + +
    +

    The tools of the trade

    +

    Assemblers and Linkers

    + + + + + +
    + + +
    
    +
    +as --32 -gstabs -o fib1.o fib1.s
    +
    +
    +ld -m elf_i386 -o fib1 fib1.o
    +
    +                
    +
    + + +
    + +
    +

    The tools of the trade

    +

    Object file utilities

    +
    +
  • nm - lists the symbols from object files +
  • objdump - displays more information about object files +
  • elfdump - similar to objdump +
  • gdb - GNU debugger +
  • gcc - GNU compiler collection +
  • make - used for build toolchains +
  • + +
    + +
    +

    The canvas

    +

    CPU and Registers

    + +
    +
    + +
    +

    The canvas

    +

    Memory Hierarchy

    + +
    +
    + +
    +

    The canvas

    +

    Registers

    + +
    +
    + +
    +

    NOP

    +
    +
    +
  • Does nothing functional +
  • Takes up a clock cycle +
  • Can be used to fill space +
  • +
    +
    
    +nop
    +          
    +
    + +
    +

    MOV

    +
    +
    +
  • MOVes (or copies) data from one location to another +
  • Can copy to/from memory, register and immediates +
  • Cannot copy from memory to memory +
    +
    + Some examples: +
    +
    
    +mov (%ebx), %eax # copy address pointed to by ebx to register eax
    +mov %ebx, (%eax) # copy value in ebx to address pointed to by eax
    +mov $1, %eax     # place value 1 into register eax
    +mov $5, (%eax)   # place value 5 into address pointed to by eax
    +mov %ebp, %esp   # copy value in register ebp into register esp
    +          
    +
  • +
    +
    +

    MOV - Operation Suffixes

    +
    +
  • Different variations based on size to copy +
  • Used for many instructions (MOVL, PUSHL, POPL, etc.) +
  • Floating point versions used with the FPU and SIMD +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    SuffixTypeBits (Integer)Bits (Floating Point)
    bbyte8-
    sshort1632
    wword16-
    llong3264
    qquad64-
    tten bytes-80
    +
    +
    + Some examples: +
    
    +movb $2, (%ebx)  # moves 0x02 into ebx
    +movw $2, (%ebx)  # moves 0x0002 into ebx
    +movl $2, (%ebx)  # moves 0x00000002 into ebx
    +          
    +
  • +
    + +
    +

    INT

    +
    +
  • Interrupts the CPU from scheduled processing +
  • Most interrupts are hardware-based +
  • Software-based interrupts are called 'soft-interrupts' +
  • Requesting actions from User Space in Kernel Space +
      +
    • Linux uses INT 0x80 +
    • MacOS uses INT 0x60 +
    • Windows uses INT 0x21 +
    +
    
    +# exit with return code 0
    +movl $1, %eax
    +movl $0, %ebx
    +int 0x80
    +          
    +
  • Modern CPUs/OSes use SYSCALL but INT is still valid +
  • +
    + +
    + +
    + +
    +

    1. Reading input from the
    command line

    +
    +
      +
    1. Reading input from the command line +
    2. Get length of command line argument +
    3. Converting input to a number +
    4. Generating the Fibonacci number +
    5. Printing the output to screen +
    +
    +
    +

    Memory Layout

    + +
    +
    +

    Command Line Arguments in the Stack

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    StackData
    ...
    ESP + n+8< pointer to second environment variable >
    ESP + n+4< pointer to first environment variable >
    ESP + n< NULL for end of command line arguments >
    ESP + n-4< pointer to last string argument >
    ...
    ESP + 12< pointer to second string argument >
    ESP + 8< pointer to a string that contains the first argument >
    ESP + 4< pointer to a string containing the name of the application >
    ESP + 0< number of arguments on command line >
    ...
    +
    + +
    +

    A Simple Print Utility

    +

    fib2.s

    +
    +
    
    +# stack args example
    +.section .text
    +.globl _start
    +  _start:
    +
    +    nop
    +    movl %esp, %ebp     # take a copy of the stack pointer esp into ebp
    +    addl $8, %ebp       # address of first arg in stack
    +    movl (%ebp), %ecx   # move the address of the first arg into ecx
    +
    +    movl $4, %edx       # set the length of our string to 4
    +    movl $4, %eax       # indicate to int 0x80 that we are doing a write
    +    movl $0, %ebx       # indicate to int 0x80 that we are writing to file descriptor 0
    +    int $0x80           # call int 0x80 for write
    +
    +    movl $1, %eax       # exit gracefully
    +    movl $0, %ebx       # with return code 0
    +    int $0x80           # call int 0x80 for exit
    +          
    +
    +
    +

    Viewing the Stack in GDB

    +

    A demo

    +
    + + +
    + + +
    +
    + +
    +

    2. Get length of command line argument

    +
    +
      +
    1. Reading input from the command line +
    2. Get length of command line argument +
    3. Converting input to a number +
    4. Generating the Fibonacci number +
    5. Printing the output to screen +
    +
    +
    +

    Approach

    +
    +
    +
  • Find address of first command line argument string +
  • Get length of string +
  • Print string to stdout +
  • +
    +
    +

    Source

    +

    fib3.s

    +
    
    +# framework - get first argument from the command line and print to stdout
    +.section .text
    +.globl _start
    +_start:
    +    nop
    +    movl %esp, %ebp     # take a copy of esp to use
    +    addl $8, %ebp       # address of first arg in stack
    +    movl (%ebp), %edi   # move arg address into esi for scasb
    +    push %edi           # store the string address as edi gets clobbered
    +
    +    movl $50, %ecx      # set ecx counter to a high value
    +    movl $0, %eax       # zero al search char
    +    movl %ecx, %ebx     # copy our max counter value to edx
    +    cld                 # set direction down
    +    repne scasb         # iterate until we find the al char
    +
    +    subl %ecx, %ebx     # subtract from our original ecx value
    +    dec %ebx            # remove null byte at the end of the string from the count
    +    pop %ecx            # restore our string address into ecx
    +    mov %ebx, %edx      # move our count value to edx for the int 80 call
    +
    +    movl $4, %eax       # set eax to 4 for int 80 to write to file
    +    movl $0, %ebx       # set ebx for file to write to as stdoout (file descriptor 0)
    +    int $0x80           # make it so
    +    movl $1, %eax       # set eax for int 80 for system exit
    +    movl $0, %ebx       # set ebx for return code 0
    +    int $0x80           # make it so again
    +          
    +
    +
    +

    Source

    +

    New Code

    +
    +
    
    +    movl (%ebp), %edi   # move arg address into esi for scasb
    +    push %edi           # store the string address as edi gets clobbered
    +
    +    movl $50, %ecx      # set ecx counter to a high value
    +    movl $0, %eax       # zero al search char
    +    movl %ecx, %ebx     # copy our max counter value to edx
    +    cld                 # set direction down
    +    repne scasb         # iterate until we find the al char
    +
    +    subl %ecx, %ebx     # subtract from our original ecx value
    +    dec %ebx            # remove null byte at the end of the string from the count
    +    pop %ecx            # restore our string address into ecx
    +    mov %ebx, %edx      # move our count value to edx for the int 80 call
    +          
    +
    + +
    +

    repne scasb

    +

    Scanning Strings

    +
    +
    +
  • edi - points to address of string to scan +
  • al - stores the byte to scan until +
  • ecx - stores the result of the scan count +
    +
    +
  • requires registers set up before running (like INT) +
    +
    +
  • the cld opcode clears the direction flag +
  • each iteration increases edi and decreases ecx +
  • +
    +
    +

    Some Arithmetic

    +
    +
    + + + + + + + + + + + + + +
    + ecx = 50 - ( len(string) + 1 ) +
    +
    + but we want len(string) +
    +
    +
    + len(string) + 1 = 50 - ecx +
    +
    + len(string) = (50 - ecx) - 1 +
    +
    +
    +
    +
    
    +subl %ecx, %ebx     # subtract from our original ecx value
    +dec %ebx            # remove null byte at the end of the string from the count
    +          
    + +
    +
    +

    Labels, CALL, RET and the Stack

    +

    labels

    +
    +
    +
  • points to an addresses in memory +
  • label addresses resolved with ld +
    +
    +
    + Standard labels: +
    my_function:
    +
    +
    + Local labels: +
    .my_local_function:
    +
  • +
    + +
    +

    Labels, CALL, RET and the Stack

    +

    CALL and RET

    +
    +
    + CALL: +
    +
  • places next instruction address on the stack +
  • jumps execution to address of label +
    +
    + RET: +
    +
  • RET jumps execution back to the next address on the stack +
  • functions are just a logical placing of CALL and RET +
  • no set order to location of labels +
  • +
    +
    +

    Functions

    +

    A Simple Example

    +
    +
    +
    
    +          call get_string_length
    +          mov %eax, %ebx
    +
    +          ...
    +
    +          get_string_length:
    +          mov $1, %eax
    +          ret
    +          
    +
    +
    +

    The implementation

    +

    fib4.s

    +
    
    +# framework - refactor into separate functions
    +.section .text
    +.globl _start
    +
    +# entrypoint of application
    +_start:
    +    nop
    +    movl %esp, %ebp     # take a copy of esp to use
    +    addl $8, %ebp       # address of first arg in stack
    +    movl (%ebp), %edi   # move arg address into esi for scasb
    +    push %edi           # store the string address as edi gets clobbered
    +    call get_string_length
    +    pop %ecx            # restore our string address into ecx
    +    call print_string
    +    call exit
    +
    +# get length of string pointed to by edi and place result in ebx
    +get_string_length:
    +    movl $50, %ecx      # set ecx counter to a high value
    +    movl $0, %eax       # zero al search char
    +    movl %ecx, %ebx     # copy our max counter value to edx
    +    cld                 # set direction down
    +    repne scasb         # iterate until we find the al char
    +    movl %ecx, %edx     # move count into edx
    +    subl %ecx, %ebx     # subtract from our original ecx value
    +    dec %ebx            # remove null byte at the end of the string from the count
    +    ret
    +
    +# print the string in ecx to the length of ebx
    +print_string:
    +    mov %ebx, %edx      # move our count value to edx for the int 80 call
    +    movl $4, %eax       # set eax to 4 for int 80 to write to file
    +    movl $0, %ebx       # set ebx for file to write to as stdoout (file descriptor 0)
    +    int $0x80           # make it so
    +    ret
    +
    +# exit the application
    +exit:
    +    movl $1, %eax       # set eax for int 80 for system exit
    +    movl $0, %ebx       # set ebx for return code 0
    +    int $0x80           # make it so again
    +          
    +
    + +
    +
    + +
    +

    3. Converting input to a number

    +
    +
      +
    1. Reading input from the command line +
    2. Get length of command line argument +
    3. Converting input to a number +
    4. Generating the Fibonacci number +
    5. Printing the output to screen +
    +
    +
    +

    long_from_string

    +

    As (pseudo) C code

    +
    +
    
    +long long_from_string(*char number_string)
    +{
    +  int i=0;
    +  long return_value=0;
    +  int temp_value=0;
    +  char digit = number_string[i];
    +
    +  while(digit >= ‘0’ && digit <= ‘9’)
    +  {
    +    temp_value = digit - 48;
    +    return_value *= 10;
    +    return_value += temp_value;
    +    digit = number_string[++i];
    +  }
    +
    +  return return_value;
    +}
    +          
    +
    + +
    +

    long_from_string

    +

    fib5.s

    +
    
    +long_from_string:
    +    xor %eax, %eax # set eax as our result register
    +    xor %ecx, %ecx # set ecx(cl) as our temporary byte register
    +.top:
    +    movb (%edi), %cl
    +    inc %edi
    +    cmpb $48, %cl  # check if value in ecx is less than ascii '0'. exit if less
    +    jl .done
    +    cmpb $57, %cl  # check if value in ecx is greater than ascii '9'. exit if greater
    +    jg .done
    +    sub $48, %cl
    +    imul $10, %eax
    +    add %ecx, %eax
    +    jmp .top
    +.done:
    +    ret
    +          
    +
    + +
    +

    ASCII

    + +
    + +
    +

    Compare and Jump Opcodes

    +
    +
    +
  • CMP compares two values and sets flags based on the result +
  • Flags include carry, zero, overflow/underflow +
  • The flags are used to jump to a label/address +
    +
    Many types of jump flags: +
  • jg = jump if greater than +
  • jl = jump if less than +
  • je = jump if equal +
  • jge = jump if greater than or equal +
  • jle = Jump if less than or equal +
  • jmp = jump unconditionally +
  • and so on. +
  • +
    + +
    +

    Relevance to Structured Programming

    +
    +
    +
  • Jumps, Compares and Labels +
  • basis of Structured Programming Constructs +
  • counters and comparisons +
    +
    + Can create: +
    +
    +
  • Selection - if..else..then +
  • Iteration - while, repeat, for, do..while +
  • +
    + +
    + +
    + +
    +

    4. Generating the Fibonacci Number

    +
    +
      +
    1. Reading input from the command line +
    2. Get length of command line argument +
    3. Converting input to a number +
    4. Generating the Fibonacci number +
    5. Printing the output to screen +
    +
    + +
    +

    The Fibonacci Function

    +

    fib6.s

    +
    
    +# input: eax holds our fibonacci n
    +# processing: iterate the fibonacci sequence n times
    +# output: return our fibonacci result in ebx
    +
    +fibonacci:
    +    pushl %ebp       # preserve ebp
    +    mov %esp, %ebp   # copy the stack pointer to ebp for use
    +    mov %eax, %ebx   # make a cpoy of our fib(n) value for allocating an array on the stack
    +    addl $2, %ebx    # add 2 extra spaces to the array size in case n=1 or n=1
    +    subl %ebx, %esp  # add the size of our array to the stack to allocate the required space
    +    xor %ecx, %ecx   # set our counter to zero
    +    movl %ecx, (%esp, %ecx, 4)  # initialise our array with 0 for esp[0]
    +    incl %ecx                   # increase our counter
    +    movl %ecx, (%esp, %ecx, 4)  # initialise our array with 1 for esp[1]
    +    incl %ecx                   # our counter/iterator should be at 2 now
    +
    +.fib_loop:
    +    cmp %eax, %ecx                # compare our counter (ecx) to n (eax)
    +    jge .fib_done                 # if it's greater or equal, we're done
    +    movl -4(%esp, %ecx, 4), %ebx  # get the value in the stack at esp-1 from our current stack pointer location
    +    movl -8(%esp, %ecx, 4), %edx  # get the value in the stack esp-2 from our current stack pointer location
    +    addl %edx, %ebx               # add the values esp-1 and esp-2 together
    +    movl %ebx, (%esp, %ecx, 4)    # place the result in the current stack location
    +    incl %ecx                     # bump our counter
    +    jmp .fib_loop                 # loop again
    +
    +.fib_done:
    +    movl %ebp, %esp               # move our copy of the stack pointer back to esp
    +    popl %ebp                     # retrieve the original copy of ebp from the stack
    +    ret
    +          
    +
    + +
    +

    Coming back to our C algorithm

    +
    +
    
    +int fib(int n)
    +{
    +  int f[n+2];
    +  int i;
    +  f[0] = 0;
    +  f[1] = 1;
    +
    +  for (i = 2; i <= n; i++)
    +  {
    +    f[i] = f[i-1] + f[i-2];
    +  }
    +  return f[n];
    +}
    +          
    + +
    +
    +

    Creating stack space

    +

    fib6.s

    +
    +
    
    +fibonacci:
    +    pushl %ebp      # preserve ebp
    +    mov %esp, %ebp  # copy the stack pointer to ebp for use
    +
    +    mov %eax, %ebx  # make a cpoy of our fib(n) value for allocating an array on the stack
    +    addl $2, %ebx   # add 2 extra spaces to the array size in case n=1 or n=1
    +    shl $2, %ebx    # multiply by 4 as we are using longs (32 bits)
    +    subl %ebx, %esp # add the size of our array to the stack to allocate the required space
    +
    +    xor %ecx, %ecx              # set our counter to zero
    +    movl %ecx, (%esp, %ecx, 4)  # initialise our array with 0 for esp[0]
    +    incl %ecx                   # increase our counter
    +    movl %ecx, (%esp, %ecx, 4)  # initialise our array with 1 for esp[1]
    +    incl %ecx                   # our counter/iterator should be at 2 now
    +        
    +
    + +
    +

    Saving the stack pointer (esp)

    +

    When modifying ESP in a function

    +
    +
    
    +fibonacci:
    +    pushl %ebp      # preserve ebp as we are going to use it to store our stack pointer for the return call
    +    mov %esp, %ebp  # copy the stack pointer to ebp for use
    +
    +...
    +
    +.fib_done:
    +    movl %ebp, %esp # move our copy of the stack pointer back to esp
    +    popl %ebp       # retrieve the original copy of ebp from the stack
    +    ret
    +          
    +
    + +
    +

    Variable initialisation

    +
    +
    +
  • using longs (32 bit values) +
  • each long is 4 bytes +
    +
    +
  • we shift left twice to multiply by 4 +
    
    +shl $2, %ebx
    +          
    +
    +
  • our stack grows downward, hence subtract for more space +
  • +
    
    +subl %ebx, %esp
    +          
    +
    + +
    +

    Indexed memory MOV formats

    +
    +

    Absolute indexed memory location

    + copy ecx into the memory address esp + ( 4 * ecx) +
    
    +movl %ecx, (%esp, %ecx, 4)
    +          
    +
    +

    Absolute and relative indexed memory

    + copy the memory location at ( esp + ( 4 * ecx) - 4 ) into ebx +
    
    +movl -4(%esp, %ecx, 4), %ebx
    +          
    +
    +

    The general rule is:

    +
    
    +relative_offset(absolute_offset, index, size)
    +          
    +
    + +
    +

    The core of the Fibonacci implementation

    +
    +
    
    +.fib_loop:                        # we begin our for loop here
    +    cmp %eax, %ecx                # compare our counter (ecx) to n (eax) if it's greater or equal, we're done
    +    jge .fib_done
    +    movl -4(%esp, %ecx, 4), %ebx  # get the value in the stack at esp-1 from our current stack pointer location
    +    movl -8(%esp, %ecx, 4), %edx  # get the value in the stack esp-2 from our current stack pointer location
    +    addl %edx, %ebx               # add the values esp-1 and esp-2 together
    +    movl %ebx, (%esp, %ecx, 4)    # place the result in the current stack location
    +    incl %ecx                     # bump our counter
    +    jmp .fib_loop                 # loop again
    +          
    +
    + +
    + +
    + +
    +

    5. Printing the output to screen

    +
    +
      +
    1. Reading input from the command line +
    2. Get length of command line argument +
    3. Converting input to a number +
    4. Generating the Fibonacci number +
    5. Printing the output to screen +
    +
    + +
    +

    print_long

    +

    fib7.s

    +
    
    +print_long:
    +    push %ebp
    +    mov %esp, %ebp              # copy the stack pointer to ebp for use
    +    add $10, %esp               # add 10 to esp to make space for our string
    +    mov $10, %ecx               # set our counter to the end of the stack space allocated (higher)
    +    mov %ebx, %eax              # our value ebx is placed into eax for division
    +.loop_pl:
    +    xor %edx, %edx              # clear edx for the dividend
    +    mov $10, %ebx               # ebx is our divisor so we set it to divide by 10
    +    div %ebx                    # do the division
    +    addb $48, %dl               # convert the quotient to ascii
    +    movb %dl, (%esp, %ecx, 1)   # place the string byte into memory
    +    dec %ecx                    # decrease our counter (as we are working backwards through the number)
    +    cmp $0, %ax                 # exit if the remainder is 0
    +    je .done_pl
    +    jmp .loop_pl                # loop again if necessary
    +.done_pl:
    +    addl %ecx, %esp             # shift our stack pointer up to the start of the buffer
    +    incl %esp                   # add 1 to the stack pointer for the actual first string byte
    +    sub $10, %ecx               # as we are counting down, we subtract 10 from ecx to give the actual number of digits
    +    neg %ecx                    # convert to a positive value
    +    mov %ecx, %edx              # move our count value to edx for the int 80 call
    +    mov %esp, %ecx              # move our string start address into ecx
    +    movl $4, %eax               # set eax to 4 for int 80 to write to file
    +    movl $0, %ebx               # set ebx for file to write to as stdoout (file descriptor 0)
    +    int $0x80                   # make it so
    +    movl %ebp, %esp             # move our copy of the stack pointer back to esp
    +    popl %ebp                   # retrieve the original copy of ebp from the stack
    +    ret
    +          
    +
    +
    +

    Overview

    +

    From comments (for brevity)

    +
    +
    +# allocate space on the stack for 10 characters
    +
    +# start a loop and check if value is zero - jump to done if so
    +
    +# divide the number by 10 and take the remainder as the first digit
    +
    +# add 48 to the number to make it an ascii value
    +
    +# store the byte in the address esp + ecx
    +
    +# jump to start of loop
    +        
    +
  • Essentially the opposite of long_to_string +
  • +
    +

    DIV

    +

    division

    +
    +
    +
  • a / b = y remainder z +
  • dividend / divisor = [ quotient, remainder ] +
  • eax / ebx = [ eax, edx ] +
    +
    +
    
    +...
    +
    +    mov %ebx, %eax              # our value ebx is placed into eax for division
    +.loop_pl:
    +    xor %edx, %edx              # clear edx for the dividend
    +    mov $10, %ebx               # ebx is our divisor so we set it to divide by 10
    +    div %ebx                    # do the division
    +    addb $48, %dl               # convert the quotient to ascii
    +
    +...
    +          
    +
  • +
    +
    +

    NEG

    +

    multiplying by -1

    +
    +
    neg %eax
    +
    +
  • takes two's compliment of number +
  • most significant bit indicates sign +
  • 1 = negative, 0 = positive +
  • number inverted and 1 added to result +
  • loose absolute range (eg. 8 bits holds -128 to 127) +
  • NEG(-12) = 12 +
  • 11110100 -> 00001011 + 1 = 00001100 +
  • +
    +
    +

    Printing to stdout

    +

    and shuffling some registers

    +
    +
    
    +mov %ecx, %edx              # move our count value to edx for the int 80 call
    +mov %esp, %ecx              # move our string start address into ecx
    +movl $4, %eax               # set eax to 4 for int 80 to write to file
    +movl $0, %ebx               # set ebx for file to write to as stdoout (file descriptor 0)
    +int $0x80                   # make it so
    +          
    +
    + +
    +
    +
    +

    Conclusion

    +

    Results and limitations

    +
    +
  • working program +
    
    +_start:
    +    nop
    +    movl %esp, %ebp              # take a copy of esp to use
    +    addl $8, %ebp                # address of first arg in stack
    +    movl (%ebp), %edi            # move arg address into esi for scasb
    +    call get_string_length       # get the length of the argument string passed in
    +    call long_from_string        # get a numeric value from our argument
    +    call check_valid_input       # if the result is zero, exit
    +    call fibonacci               # run our fibonacci sequence
    +    call print_long              # print the last value in the sequence
    +    call exit                    # exit gracefully
    +          
    +
  • no error checking +
  • limited by 32-bit +
  • sub-optimal code +
  • +
    + +
    +

    Conclusion

    +

    Most of the work doing standard library things

    + +
    + +
    +

    Conclusion

    +

    Insight into language composition

    +
    +
    +
  • Jumps are GOTOs +
  • Frowned upon in higher level languages - Djikstra +
  • Fundamental units of operation in any application +
  • +
    + +
    +

    Conclusion

    +

    It was fun!

    +
    + I got some HackerNews rep from a blog post on it! +
    + +
    + +
    +

    Conclusion

    +

    Call to action

    +
    +
    +
  • Learning continuum +
  • Learn as part of something larger +
    +
    + Helps with understanding of: +
  • LLVM +
  • eBPF +
  • GPU Assembly +
  • WebAssembly +
  • +
    + +
    + +
    +
    +

    Thank you!

    +

    + Questions? +

    +

    + @wilvk +

    + +
    +
    + + +
    + +
    + + + + + + + + + diff --git a/asm-talk/js/classList.js b/asm-talk/js/classList.js new file mode 100644 index 0000000..44f2b4c --- /dev/null +++ b/asm-talk/js/classList.js @@ -0,0 +1,2 @@ +/*! @source http://purl.eligrey.com/github/classList.js/blob/master/classList.js*/ +if(typeof document!=="undefined"&&!("classList" in document.createElement("a"))){(function(j){var a="classList",f="prototype",m=(j.HTMLElement||j.Element)[f],b=Object,k=String[f].trim||function(){return this.replace(/^\s+|\s+$/g,"")},c=Array[f].indexOf||function(q){var p=0,o=this.length;for(;p + Copyright Tero Piirainen (tipiirai) + License MIT / http://bit.ly/mit-license + Version 0.96 + + http://headjs.com +*/(function(a){function z(){d||(d=!0,s(e,function(a){p(a)}))}function y(c,d){var e=a.createElement("script");e.type="text/"+(c.type||"javascript"),e.src=c.src||c,e.async=!1,e.onreadystatechange=e.onload=function(){var a=e.readyState;!d.done&&(!a||/loaded|complete/.test(a))&&(d.done=!0,d())},(a.body||b).appendChild(e)}function x(a,b){if(a.state==o)return b&&b();if(a.state==n)return k.ready(a.name,b);if(a.state==m)return a.onpreload.push(function(){x(a,b)});a.state=n,y(a.url,function(){a.state=o,b&&b(),s(g[a.name],function(a){p(a)}),u()&&d&&s(g.ALL,function(a){p(a)})})}function w(a,b){a.state===undefined&&(a.state=m,a.onpreload=[],y({src:a.url,type:"cache"},function(){v(a)}))}function v(a){a.state=l,s(a.onpreload,function(a){a.call()})}function u(a){a=a||h;var b;for(var c in a){if(a.hasOwnProperty(c)&&a[c].state!=o)return!1;b=!0}return b}function t(a){return Object.prototype.toString.call(a)=="[object Function]"}function s(a,b){if(!!a){typeof a=="object"&&(a=[].slice.call(a));for(var c=0;c",Yt.wrapper.appendChild(e)}if(!Yt.wrapper.querySelector(".controls")){var t=document.createElement("aside");t.classList.add("controls"),t.innerHTML='',Yt.wrapper.appendChild(t)}if(!Yt.wrapper.querySelector(".state-background")){var n=document.createElement("div");n.classList.add("state-background"),Yt.wrapper.appendChild(n)}if(!Yt.wrapper.querySelector(".pause-overlay")){var r=document.createElement("div");r.classList.add("pause-overlay"),Yt.wrapper.appendChild(r)}Yt.progress=document.querySelector(".reveal .progress"),Yt.progressbar=document.querySelector(".reveal .progress span"),Pt.controls&&(Yt.controls=document.querySelector(".reveal .controls"),Yt.controlsLeft=d(document.querySelectorAll(".navigate-left")),Yt.controlsRight=d(document.querySelectorAll(".navigate-right")),Yt.controlsUp=d(document.querySelectorAll(".navigate-up")),Yt.controlsDown=d(document.querySelectorAll(".navigate-down")),Yt.controlsPrev=d(document.querySelectorAll(".navigate-prev")),Yt.controlsNext=d(document.querySelectorAll(".navigate-next")))}function n(){function e(e,t){var n={background:e.getAttribute("data-background"),backgroundSize:e.getAttribute("data-background-size"),backgroundColor:e.getAttribute("data-background-color"),backgroundRepeat:e.getAttribute("data-background-repeat"),backgroundPosition:e.getAttribute("data-background-position"),backgroundTransition:e.getAttribute("data-background-transition")},r=document.createElement("div");return r.className="slide-background",n.background&&(/^(http|file|\/\/)/gi.test(n.background)?r.style.backgroundImage="url("+n.background+")":r.style.background=n.background),n.backgroundSize&&(r.style.backgroundSize=n.backgroundSize),n.backgroundColor&&(r.style.backgroundColor=n.backgroundColor),n.backgroundRepeat&&(r.style.backgroundRepeat=n.backgroundRepeat),n.backgroundPosition&&(r.style.backgroundPosition=n.backgroundPosition),n.backgroundTransition&&r.setAttribute("data-background-transition",n.backgroundTransition),t.appendChild(r),r}v()&&document.body.classList.add("print-pdf"),Yt.background.innerHTML="",Yt.background.classList.add("no-transition"),d(document.querySelectorAll(xt)).forEach(function(t){var n;n=v()?e(t,t):e(t,Yt.background),d(t.querySelectorAll("section")).forEach(function(t){v()?e(t,t):e(t,n)})})}function r(){/iphone|ipod|android/gi.test(navigator.userAgent)&&!/crios/gi.test(navigator.userAgent)&&(window.addEventListener("load",p,!1),window.addEventListener("orientationchange",p,!1))}function o(){function e(){n.length&&head.js.apply(null,n),a()}for(var t=[],n=[],r=0,o=Pt.dependencies.length;o>r;r++){var i=Pt.dependencies[r];(!i.condition||i.condition())&&(i.async?n.push(i.src):t.push(i.src),"function"==typeof i.callback&&head.ready(i.src.match(/([\w\d_\-]*)\.?js$|[^\\\/]*$/i)[0],i.callback))}t.length?(head.ready(e),head.js.apply(null,t)):e()}function a(){t(),i(),K(),setTimeout(function(){m("ready",{indexh:Dt,indexv:Ct,currentSlide:At})},1)}function i(e){if(Yt.wrapper.classList.remove(Pt.transition),"object"==typeof e&&l(Pt,e),zt===!1&&(Pt.transition="linear"),Yt.wrapper.classList.add(Pt.transition),Yt.wrapper.setAttribute("data-transition-speed",Pt.transitionSpeed),Yt.wrapper.setAttribute("data-background-transition",Pt.backgroundTransition),Yt.controls&&(Yt.controls.style.display=Pt.controls&&Yt.controls?"block":"none"),Yt.progress&&(Yt.progress.style.display=Pt.progress&&Yt.progress?"block":"none"),Pt.rtl?Yt.wrapper.classList.add("rtl"):Yt.wrapper.classList.remove("rtl"),Pt.center?Yt.wrapper.classList.add("center"):Yt.wrapper.classList.remove("center"),Pt.mouseWheel?(document.addEventListener("DOMMouseScroll",ft,!1),document.addEventListener("mousewheel",ft,!1)):(document.removeEventListener("DOMMouseScroll",ft,!1),document.removeEventListener("mousewheel",ft,!1)),Pt.rollingLinks?h():g(),Pt.previewLinks?y():(b(),y("[data-preview-link]")),Pt.theme&&Yt.theme){var t=Yt.theme.getAttribute("href"),n=/[^\/]*?(?=\.css)/,r=t.match(n)[0];Pt.theme!==r&&(t=t.replace(n,Pt.theme),Yt.theme.setAttribute("href",t))}z()}function s(){_t=!0,window.addEventListener("hashchange",wt,!1),window.addEventListener("resize",Lt,!1),Pt.touch&&(Yt.wrapper.addEventListener("touchstart",it,!1),Yt.wrapper.addEventListener("touchmove",st,!1),Yt.wrapper.addEventListener("touchend",ct,!1),window.navigator.msPointerEnabled&&(Yt.wrapper.addEventListener("MSPointerDown",lt,!1),Yt.wrapper.addEventListener("MSPointerMove",dt,!1),Yt.wrapper.addEventListener("MSPointerUp",ut,!1))),Pt.keyboard&&document.addEventListener("keydown",at,!1),Pt.progress&&Yt.progress&&Yt.progress.addEventListener("click",vt,!1),Pt.controls&&Yt.controls&&["touchstart","click"].forEach(function(e){Yt.controlsLeft.forEach(function(t){t.addEventListener(e,pt,!1)}),Yt.controlsRight.forEach(function(t){t.addEventListener(e,mt,!1)}),Yt.controlsUp.forEach(function(t){t.addEventListener(e,ht,!1)}),Yt.controlsDown.forEach(function(t){t.addEventListener(e,gt,!1)}),Yt.controlsPrev.forEach(function(t){t.addEventListener(e,yt,!1)}),Yt.controlsNext.forEach(function(t){t.addEventListener(e,bt,!1)})})}function c(){_t=!1,document.removeEventListener("keydown",at,!1),window.removeEventListener("hashchange",wt,!1),window.removeEventListener("resize",Lt,!1),Yt.wrapper.removeEventListener("touchstart",it,!1),Yt.wrapper.removeEventListener("touchmove",st,!1),Yt.wrapper.removeEventListener("touchend",ct,!1),window.navigator.msPointerEnabled&&(Yt.wrapper.removeEventListener("MSPointerDown",lt,!1),Yt.wrapper.removeEventListener("MSPointerMove",dt,!1),Yt.wrapper.removeEventListener("MSPointerUp",ut,!1)),Pt.progress&&Yt.progress&&Yt.progress.removeEventListener("click",vt,!1),Pt.controls&&Yt.controls&&["touchstart","click"].forEach(function(e){Yt.controlsLeft.forEach(function(t){t.removeEventListener(e,pt,!1)}),Yt.controlsRight.forEach(function(t){t.removeEventListener(e,mt,!1)}),Yt.controlsUp.forEach(function(t){t.removeEventListener(e,ht,!1)}),Yt.controlsDown.forEach(function(t){t.removeEventListener(e,gt,!1)}),Yt.controlsPrev.forEach(function(t){t.removeEventListener(e,yt,!1)}),Yt.controlsNext.forEach(function(t){t.removeEventListener(e,bt,!1)})})}function l(e,t){for(var n in t)e[n]=t[n]}function d(e){return Array.prototype.slice.call(e)}function u(e,t){var n=e.x-t.x,r=e.y-t.y;return Math.sqrt(n*n+r*r)}function f(e){var t=0;if(e){var n=0;d(e.childNodes).forEach(function(e){"number"==typeof e.offsetTop&&e.style&&("absolute"===e.style.position&&(n+=1),t=Math.max(t,e.offsetTop+e.offsetHeight))}),0===n&&(t=e.offsetHeight)}return t}function v(){return/print-pdf/gi.test(window.location.search)}function p(){0===window.orientation?(document.documentElement.style.overflow="scroll",document.body.style.height="120%"):(document.documentElement.style.overflow="",document.body.style.height="100%"),setTimeout(function(){window.scrollTo(0,1)},10)}function m(e,t){var n=document.createEvent("HTMLEvents",1,2);n.initEvent(e,!0,!0),l(n,t),Yt.wrapper.dispatchEvent(n)}function h(){if(zt&&!("msPerspective"in document.body.style))for(var e=document.querySelectorAll(qt+" a:not(.image)"),t=0,n=e.length;n>t;t++){var r=e[t];if(!(!r.textContent||r.querySelector("*")||r.className&&r.classList.contains(r,"roll"))){var o=document.createElement("span");o.setAttribute("data-title",r.text),o.innerHTML=r.innerHTML,r.classList.add("roll"),r.innerHTML="",r.appendChild(o)}}}function g(){for(var e=document.querySelectorAll(qt+" a.roll"),t=0,n=e.length;n>t;t++){var r=e[t],o=r.querySelector("span");o&&(r.classList.remove("roll"),r.innerHTML=o.innerHTML)}}function y(e){var t=d(document.querySelectorAll(e?e:"a"));t.forEach(function(e){/^(http|www)/gi.test(e.getAttribute("href"))&&e.addEventListener("click",kt,!1)})}function b(){var e=d(document.querySelectorAll("a"));e.forEach(function(e){/^(http|www)/gi.test(e.getAttribute("href"))&&e.removeEventListener("click",kt,!1)})}function w(e){L(),Yt.preview=document.createElement("div"),Yt.preview.classList.add("preview-link-overlay"),Yt.wrapper.appendChild(Yt.preview),Yt.preview.innerHTML=["
    ",'','',"
    ",'
    ','
    ','',"
    "].join(""),Yt.preview.querySelector("iframe").addEventListener("load",function(){Yt.preview.classList.add("loaded")},!1),Yt.preview.querySelector(".close").addEventListener("click",function(e){L(),e.preventDefault()},!1),Yt.preview.querySelector(".external").addEventListener("click",function(){L()},!1),setTimeout(function(){Yt.preview.classList.add("visible")},1)}function L(){Yt.preview&&(Yt.preview.setAttribute("src",""),Yt.preview.parentNode.removeChild(Yt.preview),Yt.preview=null)}function E(e){var t=d(e);return t.forEach(function(e,t){e.hasAttribute("data-fragment-index")||e.setAttribute("data-fragment-index",t)}),t.sort(function(e,t){return e.getAttribute("data-fragment-index")-t.getAttribute("data-fragment-index")}),t}function k(){if(Yt.wrapper&&!v()){var e=Yt.wrapper.offsetWidth,t=Yt.wrapper.offsetHeight;e-=t*Pt.margin,t-=t*Pt.margin;var n=Pt.width,r=Pt.height;if("string"==typeof n&&/%$/.test(n)&&(n=parseInt(n,10)/100*e),"string"==typeof r&&/%$/.test(r)&&(r=parseInt(r,10)/100*t),Yt.slides.style.width=n+"px",Yt.slides.style.height=r+"px",Ot=Math.min(e/n,t/r),Ot=Math.max(Ot,Pt.minScale),Ot=Math.min(Ot,Pt.maxScale),void 0===Yt.slides.style.zoom||navigator.userAgent.match(/(iphone|ipod|ipad|android)/gi)){var o="translate(-50%, -50%) scale("+Ot+") translate(50%, 50%)";Yt.slides.style.WebkitTransform=o,Yt.slides.style.MozTransform=o,Yt.slides.style.msTransform=o,Yt.slides.style.OTransform=o,Yt.slides.style.transform=o}else Yt.slides.style.zoom=Ot;for(var a=d(document.querySelectorAll(qt)),i=0,s=a.length;s>i;i++){var c=a[i];"none"!==c.style.display&&(c.style.top=Pt.center?c.classList.contains("stack")?0:Math.max(-(f(c)/2)-20,-r/2)+"px":"")}X()}}function S(e,t){"object"==typeof e&&"function"==typeof e.setAttribute&&e.setAttribute("data-previous-indexv",t||0)}function A(e){if("object"==typeof e&&"function"==typeof e.setAttribute&&e.classList.contains("stack")){var t=e.hasAttribute("data-start-indexv")?"data-start-indexv":"data-previous-indexv";return parseInt(e.getAttribute(t)||0,10)}return 0}function q(){if(Pt.overview){G();var e=Yt.wrapper.classList.contains("overview");Yt.wrapper.classList.add("overview"),Yt.wrapper.classList.remove("exit-overview"),clearTimeout(Ut),clearTimeout(Ft),Ut=setTimeout(function(){for(var t=document.querySelectorAll(xt),n=0,r=t.length;r>n;n++){var o=t[n],a=Pt.rtl?-105:105,i="translateZ(-2500px) translate("+(n-Dt)*a+"%, 0%)";if(o.setAttribute("data-index-h",n),o.style.display="block",o.style.WebkitTransform=i,o.style.MozTransform=i,o.style.msTransform=i,o.style.OTransform=i,o.style.transform=i,o.classList.contains("stack"))for(var s=o.querySelectorAll("section"),c=0,l=s.length;l>c;c++){var d=n===Dt?Ct:A(o),u=s[c],f="translate(0%, "+105*(c-d)+"%)";u.setAttribute("data-index-h",n),u.setAttribute("data-index-v",c),u.style.display="block",u.style.WebkitTransform=f,u.style.MozTransform=f,u.style.msTransform=f,u.style.OTransform=f,u.style.transform=f,u.addEventListener("click",Et,!0)}else o.addEventListener("click",Et,!0)}k(),e||m("overviewshown",{indexh:Dt,indexv:Ct,currentSlide:At})},10)}}function x(){if(Pt.overview){clearTimeout(Ut),clearTimeout(Ft),Yt.wrapper.classList.remove("overview"),Yt.wrapper.classList.add("exit-overview"),Ft=setTimeout(function(){Yt.wrapper.classList.remove("exit-overview")},10);for(var e=d(document.querySelectorAll(qt)),t=0,n=e.length;n>t;t++){var r=e[t];r.style.display="",r.style.WebkitTransform="",r.style.MozTransform="",r.style.msTransform="",r.style.OTransform="",r.style.transform="",r.removeEventListener("click",Et,!0)}Y(Dt,Ct),B(),m("overviewhidden",{indexh:Dt,indexv:Ct,currentSlide:At})}}function T(e){"boolean"==typeof e?e?q():x():M()?x():q()}function M(){return Yt.wrapper.classList.contains("overview")}function P(e){return e=e?e:At,e&&!!e.parentNode.nodeName.match(/section/i)}function N(){var e=document.body,t=e.requestFullScreen||e.webkitRequestFullscreen||e.webkitRequestFullScreen||e.mozRequestFullScreen||e.msRequestFullScreen;t&&t.apply(e)}function D(){var e=Yt.wrapper.classList.contains("paused");G(),Yt.wrapper.classList.add("paused"),e===!1&&m("paused")}function C(){var e=Yt.wrapper.classList.contains("paused");Yt.wrapper.classList.remove("paused"),B(),e&&m("resumed")}function R(){O()?C():D()}function O(){return Yt.wrapper.classList.contains("paused")}function Y(e,t,n,r){St=At;var o=document.querySelectorAll(xt);void 0===t&&(t=A(o[e])),St&&St.parentNode&&St.parentNode.classList.contains("stack")&&S(St.parentNode,Ct);var a=Rt.concat();Rt.length=0;var i=Dt,s=Ct;Dt=H(xt,void 0===e?Dt:e),Ct=H(Tt,void 0===t?Ct:t),k();e:for(var c=0,l=Rt.length;l>c;c++){for(var u=0;a.length>u;u++)if(a[u]===Rt[c]){a.splice(u,1);continue e}document.documentElement.classList.add(Rt[c]),m(Rt[c])}for(;a.length;)document.documentElement.classList.remove(a.pop());M()&&q(),$(1500);var f=o[Dt],v=f.querySelectorAll("section");if(At=v[Ct]||f,n!==void 0){var p=E(At.querySelectorAll(".fragment"));d(p).forEach(function(e,t){n>t?e.classList.add("visible"):e.classList.remove("visible")})}var h=Dt!==i||Ct!==s;h?m("slidechanged",{indexh:Dt,indexv:Ct,previousSlide:St,currentSlide:At,origin:r}):St=null,St&&(St.classList.remove("present"),document.querySelector(Mt).classList.contains("present")&&setTimeout(function(){var e,t=d(document.querySelectorAll(xt+".stack"));for(e in t)t[e]&&S(t[e],0)},0)),h&&(j(St),_(At)),I(),X(),W()}function z(){c(),s(),k(),Nt=Pt.autoSlide,B(),n(),I(),X(),W()}function H(e,t){var n=d(document.querySelectorAll(e)),r=n.length;if(r){Pt.loop&&(t%=r,0>t&&(t=r+t)),t=Math.max(Math.min(t,r-1),0);for(var o=0;r>o;o++){var a=n[o];if(M()===!1){var i=Math.abs((t-o)%(r-3))||0;a.style.display=i>3?"none":"block"}var s=Pt.rtl&&!P(a);a.classList.remove("past"),a.classList.remove("present"),a.classList.remove("future"),a.setAttribute("hidden",""),t>o?a.classList.add(s?"future":"past"):o>t&&a.classList.add(s?"past":"future"),a.querySelector("section")&&a.classList.add("stack")}n[t].classList.add("present"),n[t].removeAttribute("hidden");var c=n[t].getAttribute("data-state");c&&(Rt=Rt.concat(c.split(" ")));var l=n[t].getAttribute("data-autoslide");Nt=l?parseInt(l,10):Pt.autoSlide}else t=0;return t}function X(){if(Pt.progress&&Yt.progress){var e=d(document.querySelectorAll(xt)),t=document.querySelectorAll(qt+":not(.stack)").length,n=0;e:for(var r=0;e.length>r;r++){for(var o=e[r],a=d(o.querySelectorAll("section")),i=0;a.length>i;i++){if(a[i].classList.contains("present"))break e;n++}if(o.classList.contains("present"))break;o.classList.contains("stack")===!1&&n++}Yt.progressbar.style.width=n/(t-1)*window.innerWidth+"px"}}function I(){if(Pt.controls&&Yt.controls){var e=U(),t=F();Yt.controlsLeft.concat(Yt.controlsRight).concat(Yt.controlsUp).concat(Yt.controlsDown).concat(Yt.controlsPrev).concat(Yt.controlsNext).forEach(function(e){e.classList.remove("enabled"),e.classList.remove("fragmented")}),e.left&&Yt.controlsLeft.forEach(function(e){e.classList.add("enabled")}),e.right&&Yt.controlsRight.forEach(function(e){e.classList.add("enabled")}),e.up&&Yt.controlsUp.forEach(function(e){e.classList.add("enabled")}),e.down&&Yt.controlsDown.forEach(function(e){e.classList.add("enabled")}),(e.left||e.up)&&Yt.controlsPrev.forEach(function(e){e.classList.add("enabled")}),(e.right||e.down)&&Yt.controlsNext.forEach(function(e){e.classList.add("enabled")}),At&&(t.prev&&Yt.controlsPrev.forEach(function(e){e.classList.add("fragmented","enabled")}),t.next&&Yt.controlsNext.forEach(function(e){e.classList.add("fragmented","enabled")}),P(At)?(t.prev&&Yt.controlsUp.forEach(function(e){e.classList.add("fragmented","enabled")}),t.next&&Yt.controlsDown.forEach(function(e){e.classList.add("fragmented","enabled")})):(t.prev&&Yt.controlsLeft.forEach(function(e){e.classList.add("fragmented","enabled")}),t.next&&Yt.controlsRight.forEach(function(e){e.classList.add("fragmented","enabled")})))}}function W(){d(Yt.background.childNodes).forEach(function(e,t){var n=Pt.rtl?"future":"past",r=Pt.rtl?"past":"future";e.className="slide-background "+(Dt>t?n:t>Dt?r:"present"),d(e.childNodes).forEach(function(e,t){e.className="slide-background "+(Ct>t?"past":t>Ct?"future":"present")})}),setTimeout(function(){Yt.background.classList.remove("no-transition")},1)}function U(){var e=document.querySelectorAll(xt),t=document.querySelectorAll(Tt),n={left:Dt>0||Pt.loop,right:e.length-1>Dt||Pt.loop,up:Ct>0,down:t.length-1>Ct};if(Pt.rtl){var r=n.left;n.left=n.right,n.right=r}return n}function F(){if(At&&Pt.fragments){var e=At.querySelectorAll(".fragment"),t=At.querySelectorAll(".fragment:not(.visible)");return{prev:e.length-t.length>0,next:!!t.length}}return{prev:!1,next:!1}}function _(e){e&&(d(e.querySelectorAll("video, audio")).forEach(function(e){e.hasAttribute("data-autoplay")&&e.play()}),d(e.querySelectorAll('iframe[src*="youtube.com/embed/"]')).forEach(function(e){e.hasAttribute("data-autoplay")&&e.contentWindow.postMessage('{"event":"command","func":"playVideo","args":""}',"*")}))}function j(e){e&&(d(e.querySelectorAll("video, audio")).forEach(function(e){e.hasAttribute("data-ignore")||e.pause()}),d(e.querySelectorAll('iframe[src*="youtube.com/embed/"]')).forEach(function(e){e.hasAttribute("data-ignore")||"function"!=typeof e.contentWindow.postMessage||e.contentWindow.postMessage('{"event":"command","func":"pauseVideo","args":""}',"*")}))}function K(){var e=window.location.hash,t=e.slice(2).split("/"),n=e.replace(/#|\//gi,"");if(isNaN(parseInt(t[0],10))&&n.length){var r=document.querySelector("#"+n);if(r){var o=Reveal.getIndices(r);Y(o.h,o.v)}else Y(Dt,Ct)}else{var a=parseInt(t[0],10)||0,i=parseInt(t[1],10)||0;Y(a,i)}}function $(e){if(Pt.history)if(clearTimeout(Wt),"number"==typeof e)Wt=setTimeout($,e);else{var t="/";At&&"string"==typeof At.getAttribute("id")?t="/"+At.getAttribute("id"):((Dt>0||Ct>0)&&(t+=Dt),Ct>0&&(t+="/"+Ct)),window.location.hash=t}}function V(e){var t,n=Dt,r=Ct;if(e){var o=P(e),a=o?e.parentNode:e,i=d(document.querySelectorAll(xt));n=Math.max(i.indexOf(a),0),o&&(r=Math.max(d(e.parentNode.querySelectorAll("section")).indexOf(e),0))}if(!e&&At){var s=At.querySelectorAll(".fragment.visible");s.length&&(t=s.length)}return{h:n,v:r,f:t}}function Z(){if(At&&Pt.fragments){var e=E(At.querySelectorAll(".fragment:not(.visible)"));if(e.length){var t=e[0].getAttribute("data-fragment-index");return e=At.querySelectorAll('.fragment[data-fragment-index="'+t+'"]'),d(e).forEach(function(e){e.classList.add("visible"),m("fragmentshown",{fragment:e})}),I(),!0}}return!1}function Q(){if(At&&Pt.fragments){var e=E(At.querySelectorAll(".fragment.visible"));if(e.length){var t=e[e.length-1].getAttribute("data-fragment-index");return e=At.querySelectorAll('.fragment[data-fragment-index="'+t+'"]'),d(e).forEach(function(e){e.classList.remove("visible"),m("fragmenthidden",{fragment:e})}),I(),!0}}return!1}function B(){clearTimeout(It),!Nt||O()||M()||(It=setTimeout(ot,Nt))}function G(){clearTimeout(It)}function J(){Pt.rtl?(M()||Z()===!1)&&U().left&&Y(Dt+1):(M()||Q()===!1)&&U().left&&Y(Dt-1)}function et(){Pt.rtl?(M()||Q()===!1)&&U().right&&Y(Dt-1):(M()||Z()===!1)&&U().right&&Y(Dt+1)}function tt(){(M()||Q()===!1)&&U().up&&Y(Dt,Ct-1)}function nt(){(M()||Z()===!1)&&U().down&&Y(Dt,Ct+1)}function rt(){if(Q()===!1)if(U().up)tt();else{var e=document.querySelector(xt+".past:nth-child("+Dt+")");if(e){var t=e.querySelectorAll("section").length-1||void 0,n=Dt-1;Y(n,t)}}}function ot(){Z()===!1&&(U().down?nt():et()),B()}function at(e){document.activeElement;var t=!(!document.activeElement||!document.activeElement.type&&!document.activeElement.href&&"inherit"===document.activeElement.contentEditable);if(!(t||e.shiftKey&&32!==e.keyCode||e.altKey||e.ctrlKey||e.metaKey)){if(O()&&-1===[66,190,191].indexOf(e.keyCode))return!1;var n=!1;if("object"==typeof Pt.keyboard)for(var r in Pt.keyboard)if(parseInt(r,10)===e.keyCode){var o=Pt.keyboard[r];"function"==typeof o?o.apply(null,[e]):"string"==typeof o&&"function"==typeof Reveal[o]&&Reveal[o].call(),n=!0}if(n===!1)switch(n=!0,e.keyCode){case 80:case 33:rt();break;case 78:case 34:ot();break;case 72:case 37:J();break;case 76:case 39:et();break;case 75:case 38:tt();break;case 74:case 40:nt();break;case 36:Y(0);break;case 35:Y(Number.MAX_VALUE);break;case 32:M()?x():e.shiftKey?rt():ot();break;case 13:M()?x():n=!1;break;case 66:case 190:case 191:R();break;case 70:N();break;default:n=!1}n?e.preventDefault():27===e.keyCode&&zt&&(T(),e.preventDefault()),B()}}function it(e){jt.startX=e.touches[0].clientX,jt.startY=e.touches[0].clientY,jt.startCount=e.touches.length,2===e.touches.length&&Pt.overview&&(jt.startSpan=u({x:e.touches[1].clientX,y:e.touches[1].clientY},{x:jt.startX,y:jt.startY}))}function st(e){if(jt.handled)navigator.userAgent.match(/android/gi)&&e.preventDefault();else{var t=e.touches[0].clientX,n=e.touches[0].clientY;if(2===e.touches.length&&2===jt.startCount&&Pt.overview){var r=u({x:e.touches[1].clientX,y:e.touches[1].clientY},{x:jt.startX,y:jt.startY});Math.abs(jt.startSpan-r)>jt.threshold&&(jt.handled=!0,jt.startSpan>r?q():x()),e.preventDefault()}else if(1===e.touches.length&&2!==jt.startCount){var o=t-jt.startX,a=n-jt.startY;o>jt.threshold&&Math.abs(o)>Math.abs(a)?(jt.handled=!0,J()):-jt.threshold>o&&Math.abs(o)>Math.abs(a)?(jt.handled=!0,et()):a>jt.threshold?(jt.handled=!0,tt()):-jt.threshold>a&&(jt.handled=!0,nt()),e.preventDefault()}}}function ct(){jt.handled=!1}function lt(e){e.pointerType===e.MSPOINTER_TYPE_TOUCH&&(e.touches=[{clientX:e.clientX,clientY:e.clientY}],it(e))}function dt(e){e.pointerType===e.MSPOINTER_TYPE_TOUCH&&(e.touches=[{clientX:e.clientX,clientY:e.clientY}],st(e))}function ut(e){e.pointerType===e.MSPOINTER_TYPE_TOUCH&&(e.touches=[{clientX:e.clientX,clientY:e.clientY}],ct(e))}function ft(e){if(Date.now()-Xt>600){Xt=Date.now();var t=e.detail||-e.wheelDelta;t>0?ot():rt()}}function vt(e){e.preventDefault();var t=d(document.querySelectorAll(xt)).length,n=Math.floor(e.clientX/Yt.wrapper.offsetWidth*t);Y(n)}function pt(e){e.preventDefault(),J()}function mt(e){e.preventDefault(),et()}function ht(e){e.preventDefault(),tt()}function gt(e){e.preventDefault(),nt()}function yt(e){e.preventDefault(),rt()}function bt(e){e.preventDefault(),ot()}function wt(){K()}function Lt(){k()}function Et(e){if(_t&&M()){e.preventDefault();for(var t=e.target;t&&!t.nodeName.match(/section/gi);)t=t.parentNode;if(t&&!t.classList.contains("disabled")&&(x(),t.nodeName.match(/section/gi))){var n=parseInt(t.getAttribute("data-index-h"),10),r=parseInt(t.getAttribute("data-index-v"),10);Y(n,r)}}}function kt(e){var t=e.target.getAttribute("href");t&&(w(t),e.preventDefault())}var St,At,qt=".reveal .slides section",xt=".reveal .slides>section",Tt=".reveal .slides>section.present>section",Mt=".reveal .slides>section:first-child",Pt={width:960,height:700,margin:.1,minScale:.2,maxScale:1,controls:!0,progress:!0,history:!1,keyboard:!0,overview:!0,center:!0,touch:!0,loop:!1,rtl:!1,fragments:!0,autoSlide:0,mouseWheel:!1,rollingLinks:!0,previewLinks:!1,theme:null,transition:"default",transitionSpeed:"default",backgroundTransition:"default",dependencies:[]},Nt=0,Dt=0,Ct=0,Rt=[],Ot=1,Yt={},zt="WebkitPerspective"in document.body.style||"MozPerspective"in document.body.style||"msPerspective"in document.body.style||"OPerspective"in document.body.style||"perspective"in document.body.style,Ht="WebkitTransform"in document.body.style||"MozTransform"in document.body.style||"msTransform"in document.body.style||"OTransform"in document.body.style||"transform"in document.body.style,Xt=0,It=0,Wt=0,Ut=0,Ft=0,_t=!1,jt={startX:0,startY:0,startSpan:0,startCount:0,handled:!1,threshold:80};return{initialize:e,configure:i,sync:z,slide:Y,left:J,right:et,up:tt,down:nt,prev:rt,next:ot,prevFragment:Q,nextFragment:Z,navigateTo:Y,navigateLeft:J,navigateRight:et,navigateUp:tt,navigateDown:nt,navigatePrev:rt,navigateNext:ot,layout:k,availableRoutes:U,availableFragments:F,toggleOverview:T,togglePause:R,isOverview:M,isPaused:O,addEventListeners:s,removeEventListeners:c,getIndices:V,getSlide:function(e,t){var n=document.querySelectorAll(xt)[e],r=n&&n.querySelectorAll("section");return t!==void 0?r?r[t]:void 0:n},getPreviousSlide:function(){return St},getCurrentSlide:function(){return At},getScale:function(){return Ot},getConfig:function(){return Pt},getQueryHash:function(){var e={};return location.search.replace(/[A-Z0-9]+?=(\w*)/gi,function(t){e[t.split("=").shift()]=t.split("=").pop()}),e},isFirstSlide:function(){return null==document.querySelector(qt+".past")?!0:!1},isLastSlide:function(){return At&&At.classList.contains(".stack")?null==At.querySelector(qt+".future")?!0:!1:null==document.querySelector(qt+".future")?!0:!1},addEventListener:function(e,t,n){"addEventListener"in window&&(Yt.wrapper||document.querySelector(".reveal")).addEventListener(e,t,n)},removeEventListener:function(e,t,n){"addEventListener"in window&&(Yt.wrapper||document.querySelector(".reveal")).removeEventListener(e,t,n)}}}(); \ No newline at end of file diff --git a/asm-talk/plugin/highlight/highlight.js b/asm-talk/plugin/highlight/highlight.js new file mode 100644 index 0000000..2091fb5 --- /dev/null +++ b/asm-talk/plugin/highlight/highlight.js @@ -0,0 +1,30 @@ +// START CUSTOM REVEAL.JS INTEGRATION +(function() { + if( typeof window.addEventListener === 'function' ) { + var hljs_nodes = document.querySelectorAll( 'pre code' ); + + for( var i = 0, len = hljs_nodes.length; i < len; i++ ) { + var element = hljs_nodes[i]; + + // trim whitespace if data-trim attribute is present + if( element.hasAttribute( 'data-trim' ) && typeof element.innerHTML.trim === 'function' ) { + element.innerHTML = element.innerHTML.trim(); + } + + // Now escape html unless prevented by author + if( ! element.hasAttribute( 'data-noescape' )) { + element.innerHTML = element.innerHTML.replace(//g,">"); + } + + // re-highlight when focus is lost (for edited code) + element.addEventListener( 'focusout', function( event ) { + hljs.highlightBlock( event.currentTarget ); + }, false ); + } + } +})(); +// END CUSTOM REVEAL.JS INTEGRATION + +// highlight.js build includes support for: +// Bash, C#, C++, CSS, Diff, HTML, XML, HTTP, Ini, JSON, Java, JavaScript, PHP, Perl, Python, Ruby, SQL, Clojure, GLSL, Lua, Scala, CoffeeScript, Go, Objective C, ActionScript, Markdown +var hljs=new function(){function l(o){return o.replace(/&/gm,"&").replace(//gm,">")}function b(p){for(var o=p.firstChild;o;o=o.nextSibling){if(o.nodeName=="CODE"){return o}if(!(o.nodeType==3&&o.nodeValue.match(/\s+/))){break}}}function h(p,o){return Array.prototype.map.call(p.childNodes,function(q){if(q.nodeType==3){return o?q.nodeValue.replace(/\n/g,""):q.nodeValue}if(q.nodeName=="BR"){return"\n"}return h(q,o)}).join("")}function a(q){var p=(q.className+" "+q.parentNode.className).split(/\s+/);p=p.map(function(r){return r.replace(/^language-/,"")});for(var o=0;o"}while(x.length||v.length){var u=t().splice(0,1)[0];y+=l(w.substr(p,u.offset-p));p=u.offset;if(u.event=="start"){y+=s(u.node);r.push(u.node)}else{if(u.event=="stop"){var o,q=r.length;do{q--;o=r[q];y+=("")}while(o!=u.node);r.splice(q,1);while(q'+L[0]+""}else{r+=L[0]}N=A.lR.lastIndex;L=A.lR.exec(K)}return r+K.substr(N)}function z(){if(A.sL&&!e[A.sL]){return l(w)}var r=A.sL?d(A.sL,w):g(w);if(A.r>0){v+=r.keyword_count;B+=r.r}return''+r.value+""}function J(){return A.sL!==undefined?z():G()}function I(L,r){var K=L.cN?'':"";if(L.rB){x+=K;w=""}else{if(L.eB){x+=l(r)+K;w=""}else{x+=K;w=r}}A=Object.create(L,{parent:{value:A}});B+=L.r}function C(K,r){w+=K;if(r===undefined){x+=J();return 0}var L=o(r,A);if(L){x+=J();I(L,r);return L.rB?0:r.length}var M=s(A,r);if(M){if(!(M.rE||M.eE)){w+=r}x+=J();do{if(A.cN){x+=""}A=A.parent}while(A!=M.parent);if(M.eE){x+=l(r)}w="";if(M.starts){I(M.starts,"")}return M.rE?0:r.length}if(t(r,A)){throw"Illegal"}w+=r;return r.length||1}var F=e[D];f(F);var A=F;var w="";var B=0;var v=0;var x="";try{var u,q,p=0;while(true){A.t.lastIndex=p;u=A.t.exec(E);if(!u){break}q=C(E.substr(p,u.index-p),u[0]);p=u.index+q}C(E.substr(p));return{r:B,keyword_count:v,value:x,language:D}}catch(H){if(H=="Illegal"){return{r:0,keyword_count:0,value:l(E)}}else{throw H}}}function g(s){var o={keyword_count:0,r:0,value:l(s)};var q=o;for(var p in e){if(!e.hasOwnProperty(p)){continue}var r=d(p,s);r.language=p;if(r.keyword_count+r.r>q.keyword_count+q.r){q=r}if(r.keyword_count+r.r>o.keyword_count+o.r){q=o;o=r}}if(q.language){o.second_best=q}return o}function i(q,p,o){if(p){q=q.replace(/^((<[^>]+>|\t)+)/gm,function(r,v,u,t){return v.replace(/\t/g,p)})}if(o){q=q.replace(/\n/g,"
    ")}return q}function m(r,u,p){var v=h(r,p);var t=a(r);if(t=="no-highlight"){return}var w=t?d(t,v):g(v);t=w.language;var o=c(r);if(o.length){var q=document.createElement("pre");q.innerHTML=w.value;w.value=j(o,c(q),v)}w.value=i(w.value,u,p);var s=r.className;if(!s.match("(\\s|^)(language-)?"+t+"(\\s|$)")){s=s?(s+" "+t):t}r.innerHTML=w.value;r.className=s;r.result={language:t,kw:w.keyword_count,re:w.r};if(w.second_best){r.second_best={language:w.second_best.language,kw:w.second_best.keyword_count,re:w.second_best.r}}}function n(){if(n.called){return}n.called=true;Array.prototype.map.call(document.getElementsByTagName("pre"),b).filter(Boolean).forEach(function(o){m(o,hljs.tabReplace)})}function k(){window.addEventListener("DOMContentLoaded",n,false);window.addEventListener("load",n,false)}var e={};this.LANGUAGES=e;this.highlight=d;this.highlightAuto=g;this.fixMarkup=i;this.highlightBlock=m;this.initHighlighting=n;this.initHighlightingOnLoad=k;this.IR="[a-zA-Z][a-zA-Z0-9_]*";this.UIR="[a-zA-Z_][a-zA-Z0-9_]*";this.NR="\\b\\d+(\\.\\d+)?";this.CNR="(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)";this.BNR="\\b(0b[01]+)";this.RSR="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|\\.|-|-=|/|/=|:|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~";this.BE={b:"\\\\[\\s\\S]",r:0};this.ASM={cN:"string",b:"'",e:"'",i:"\\n",c:[this.BE],r:0};this.QSM={cN:"string",b:'"',e:'"',i:"\\n",c:[this.BE],r:0};this.CLCM={cN:"comment",b:"//",e:"$"};this.CBLCLM={cN:"comment",b:"/\\*",e:"\\*/"};this.HCM={cN:"comment",b:"#",e:"$"};this.NM={cN:"number",b:this.NR,r:0};this.CNM={cN:"number",b:this.CNR,r:0};this.BNM={cN:"number",b:this.BNR,r:0};this.inherit=function(q,r){var o={};for(var p in q){o[p]=q[p]}if(r){for(var p in r){o[p]=r[p]}}return o}}();hljs.LANGUAGES.bash=function(a){var g="true false";var e="if then else elif fi for break continue while in do done echo exit return set declare";var c={cN:"variable",b:"\\$[a-zA-Z0-9_#]+"};var b={cN:"variable",b:"\\${([^}]|\\\\})+}"};var h={cN:"string",b:'"',e:'"',i:"\\n",c:[a.BE,c,b],r:0};var d={cN:"string",b:"'",e:"'",c:[{b:"''"}],r:0};var f={cN:"test_condition",b:"",e:"",c:[h,d,c,b],k:{literal:g},r:0};return{k:{keyword:e,literal:g},c:[{cN:"shebang",b:"(#!\\/bin\\/bash)|(#!\\/bin\\/sh)",r:10},c,b,a.HCM,h,d,a.inherit(f,{b:"\\[ ",e:" \\]",r:0}),a.inherit(f,{b:"\\[\\[ ",e:" \\]\\]"})]}}(hljs);hljs.LANGUAGES.ruby=function(e){var a="[a-zA-Z_][a-zA-Z0-9_]*(\\!|\\?)?";var j="[a-zA-Z_]\\w*[!?=]?|[-+~]\\@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?";var g={keyword:"and false then defined module in return redo if BEGIN retry end for true self when next until do begin unless END rescue nil else break undef not super class case require yield alias while ensure elsif or include"};var c={cN:"yardoctag",b:"@[A-Za-z]+"};var k=[{cN:"comment",b:"#",e:"$",c:[c]},{cN:"comment",b:"^\\=begin",e:"^\\=end",c:[c],r:10},{cN:"comment",b:"^__END__",e:"\\n$"}];var d={cN:"subst",b:"#\\{",e:"}",l:a,k:g};var i=[e.BE,d];var b=[{cN:"string",b:"'",e:"'",c:i,r:0},{cN:"string",b:'"',e:'"',c:i,r:0},{cN:"string",b:"%[qw]?\\(",e:"\\)",c:i},{cN:"string",b:"%[qw]?\\[",e:"\\]",c:i},{cN:"string",b:"%[qw]?{",e:"}",c:i},{cN:"string",b:"%[qw]?<",e:">",c:i,r:10},{cN:"string",b:"%[qw]?/",e:"/",c:i,r:10},{cN:"string",b:"%[qw]?%",e:"%",c:i,r:10},{cN:"string",b:"%[qw]?-",e:"-",c:i,r:10},{cN:"string",b:"%[qw]?\\|",e:"\\|",c:i,r:10}];var h={cN:"function",bWK:true,e:" |$|;",k:"def",c:[{cN:"title",b:j,l:a,k:g},{cN:"params",b:"\\(",e:"\\)",l:a,k:g}].concat(k)};var f=k.concat(b.concat([{cN:"class",bWK:true,e:"$|;",k:"class module",c:[{cN:"title",b:"[A-Za-z_]\\w*(::\\w+)*(\\?|\\!)?",r:0},{cN:"inheritance",b:"<\\s*",c:[{cN:"parent",b:"("+e.IR+"::)?"+e.IR}]}].concat(k)},h,{cN:"constant",b:"(::)?(\\b[A-Z]\\w*(::)?)+",r:0},{cN:"symbol",b:":",c:b.concat([{b:j}]),r:0},{cN:"symbol",b:a+":",r:0},{cN:"number",b:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",r:0},{cN:"number",b:"\\?\\w"},{cN:"variable",b:"(\\$\\W)|((\\$|\\@\\@?)(\\w+))"},{b:"("+e.RSR+")\\s*",c:k.concat([{cN:"regexp",b:"/",e:"/[a-z]*",i:"\\n",c:[e.BE,d]}]),r:0}]));d.c=f;h.c[1].c=f;return{l:a,k:g,c:f}}(hljs); diff --git a/asm-talk/plugin/markdown/markdown.js b/asm-talk/plugin/markdown/markdown.js new file mode 100644 index 0000000..42c847f --- /dev/null +++ b/asm-talk/plugin/markdown/markdown.js @@ -0,0 +1,320 @@ +/** + * The reveal.js markdown plugin. Handles parsing of + * markdown inside of presentations as well as loading + * of external markdown documents. + */ +(function( root, factory ) { + if( typeof exports === 'object' ) { + module.exports = factory( require( './marked' ) ); + } + else { + // Browser globals (root is window) + root.RevealMarkdown = factory( root.marked ); + root.RevealMarkdown.initialize(); + } +}( this, function( marked ) { + + if( typeof marked === 'undefined' ) { + throw 'The reveal.js Markdown plugin requires marked to be loaded'; + } + + if( typeof hljs !== 'undefined' ) { + marked.setOptions({ + highlight: function( lang, code ) { + return hljs.highlightAuto( lang, code ).value; + } + }); + } + + var DEFAULT_SLIDE_SEPARATOR = '^\n---\n$', + DEFAULT_NOTES_SEPARATOR = 'note:'; + + + /** + * Retrieves the markdown contents of a slide section + * element. Normalizes leading tabs/whitespace. + */ + function getMarkdownFromSlide( section ) { + + var template = section.querySelector( 'script' ); + + // strip leading whitespace so it isn't evaluated as code + var text = ( template || section ).textContent; + + var leadingWs = text.match( /^\n?(\s*)/ )[1].length, + leadingTabs = text.match( /^\n?(\t*)/ )[1].length; + + if( leadingTabs > 0 ) { + text = text.replace( new RegExp('\\n?\\t{' + leadingTabs + '}','g'), '\n' ); + } + else if( leadingWs > 1 ) { + text = text.replace( new RegExp('\\n? {' + leadingWs + '}','g'), '\n' ); + } + + return text; + + } + + /** + * Given a markdown slide section element, this will + * return all arguments that aren't related to markdown + * parsing. Used to forward any other user-defined arguments + * to the output markdown slide. + */ + function getForwardedAttributes( section ) { + + var attributes = section.attributes; + var result = []; + + for( var i = 0, len = attributes.length; i < len; i++ ) { + var name = attributes[i].name, + value = attributes[i].value; + + // disregard attributes that are used for markdown loading/parsing + if( /data\-(markdown|separator|vertical|notes)/gi.test( name ) ) continue; + + if( value ) { + result.push( name + '=' + value ); + } + else { + result.push( name ); + } + } + + return result.join( ' ' ); + + } + + /** + * Inspects the given options and fills out default + * values for what's not defined. + */ + function getSlidifyOptions( options ) { + + options = options || {}; + options.separator = options.separator || DEFAULT_SLIDE_SEPARATOR; + options.notesSeparator = options.notesSeparator || DEFAULT_NOTES_SEPARATOR; + options.attributes = options.attributes || ''; + + return options; + + } + + /** + * Helper function for constructing a markdown slide. + */ + function createMarkdownSlide( content, options ) { + + options = getSlidifyOptions( options ); + + var notesMatch = content.split( new RegExp( options.notesSeparator, 'mgi' ) ); + + if( notesMatch.length === 2 ) { + content = notesMatch[0] + ''; + } + + return ''; + + } + + /** + * Parses a data string into multiple slides based + * on the passed in separator arguments. + */ + function slidify( markdown, options ) { + + options = getSlidifyOptions( options ); + + var separatorRegex = new RegExp( options.separator + ( options.verticalSeparator ? '|' + options.verticalSeparator : '' ), 'mg' ), + horizontalSeparatorRegex = new RegExp( options.separator ); + + var matches, + lastIndex = 0, + isHorizontal, + wasHorizontal = true, + content, + sectionStack = []; + + // iterate until all blocks between separators are stacked up + while( matches = separatorRegex.exec( markdown ) ) { + notes = null; + + // determine direction (horizontal by default) + isHorizontal = horizontalSeparatorRegex.test( matches[0] ); + + if( !isHorizontal && wasHorizontal ) { + // create vertical stack + sectionStack.push( [] ); + } + + // pluck slide content from markdown input + content = markdown.substring( lastIndex, matches.index ); + + if( isHorizontal && wasHorizontal ) { + // add to horizontal stack + sectionStack.push( content ); + } + else { + // add to vertical stack + sectionStack[sectionStack.length-1].push( content ); + } + + lastIndex = separatorRegex.lastIndex; + wasHorizontal = isHorizontal; + } + + // add the remaining slide + ( wasHorizontal ? sectionStack : sectionStack[sectionStack.length-1] ).push( markdown.substring( lastIndex ) ); + + var markdownSections = ''; + + // flatten the hierarchical stack, and insert
    tags + for( var i = 0, len = sectionStack.length; i < len; i++ ) { + // vertical + if( sectionStack[i].propertyIsEnumerable( length ) && typeof sectionStack[i].splice === 'function' ) { + markdownSections += '
    '; + + sectionStack[i].forEach( function( child ) { + markdownSections += '
    ' + createMarkdownSlide( child, options ) + '
    '; + } ); + + markdownSections += '
    '; + } + else { + markdownSections += '
    ' + createMarkdownSlide( sectionStack[i], options ) + '
    '; + } + } + + return markdownSections; + + } + + /** + * Parses any current data-markdown slides, splits + * multi-slide markdown into separate sections and + * handles loading of external markdown. + */ + function processSlides() { + + var sections = document.querySelectorAll( '[data-markdown]'), + section; + + for( var i = 0, len = sections.length; i < len; i++ ) { + + section = sections[i]; + + if( section.getAttribute( 'data-markdown' ).length ) { + + var xhr = new XMLHttpRequest(), + url = section.getAttribute( 'data-markdown' ); + + datacharset = section.getAttribute( 'data-charset' ); + + // see https://developer.mozilla.org/en-US/docs/Web/API/element.getAttribute#Notes + if( datacharset != null && datacharset != '' ) { + xhr.overrideMimeType( 'text/html; charset=' + datacharset ); + } + + xhr.onreadystatechange = function() { + if( xhr.readyState === 4 ) { + if ( xhr.status >= 200 && xhr.status < 300 ) { + + section.outerHTML = slidify( xhr.responseText, { + separator: section.getAttribute( 'data-separator' ), + verticalSeparator: section.getAttribute( 'data-vertical' ), + notesSeparator: section.getAttribute( 'data-notes' ), + attributes: getForwardedAttributes( section ) + }); + + } + else { + + section.outerHTML = '
    ' + + 'ERROR: The attempt to fetch ' + url + ' failed with HTTP status ' + xhr.status + '.' + + 'Check your browser\'s JavaScript console for more details.' + + '

    Remember that you need to serve the presentation HTML from a HTTP server.

    ' + + '
    '; + + } + } + }; + + xhr.open( 'GET', url, false ); + + try { + xhr.send(); + } + catch ( e ) { + alert( 'Failed to get the Markdown file ' + url + '. Make sure that the presentation and the file are served by a HTTP server and the file can be found there. ' + e ); + } + + } + else if( section.getAttribute( 'data-separator' ) || section.getAttribute( 'data-vertical' ) || section.getAttribute( 'data-notes' ) ) { + + section.outerHTML = slidify( getMarkdownFromSlide( section ), { + separator: section.getAttribute( 'data-separator' ), + verticalSeparator: section.getAttribute( 'data-vertical' ), + notesSeparator: section.getAttribute( 'data-notes' ), + attributes: getForwardedAttributes( section ) + }); + + } + else { + + section.innerHTML = createMarkdownSlide( getMarkdownFromSlide( section ) ); + + } + } + + } + + /** + * Converts any current data-markdown slides in the + * DOM to HTML. + */ + function convertSlides() { + + var sections = document.querySelectorAll( '[data-markdown]'); + + for( var i = 0, len = sections.length; i < len; i++ ) { + + var section = sections[i]; + + // Only parse the same slide once + if( !section.getAttribute( 'data-markdown-parsed' ) ) { + + section.setAttribute( 'data-markdown-parsed', true ) + + var notes = section.querySelector( 'aside.notes' ); + var markdown = getMarkdownFromSlide( section ); + + section.innerHTML = marked( markdown ); + + // If there were notes, we need to re-add them after + // having overwritten the section's HTML + if( notes ) { + section.appendChild( notes ); + } + + } + + } + + } + + // API + return { + + initialize: function() { + processSlides(); + convertSlides(); + }, + + // TODO: Do these belong in the API? + processSlides: processSlides, + convertSlides: convertSlides, + slidify: slidify + + }; + +})); diff --git a/asm-talk/plugin/markdown/marked.js b/asm-talk/plugin/markdown/marked.js new file mode 100644 index 0000000..ca558fb --- /dev/null +++ b/asm-talk/plugin/markdown/marked.js @@ -0,0 +1,37 @@ +/** + * marked - a markdown parser + * Copyright (c) 2011-2013, Christopher Jeffrey. (MIT Licensed) + * https://github.com/chjj/marked + */ + +(function(){var block={newline:/^\n+/,code:/^( {4}[^\n]+\n*)+/,fences:noop,hr:/^( *[-*_]){3,} *(?:\n+|$)/,heading:/^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,nptable:noop,lheading:/^([^\n]+)\n *(=|-){3,} *\n*/,blockquote:/^( *>[^\n]+(\n[^\n]+)*\n*)+/,list:/^( *)(bull) [\s\S]+?(?:hr|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,html:/^ *(?:comment|closed|closing) *(?:\n{2,}|\s*$)/,def:/^ *\[([^\]]+)\]: *]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,table:noop,paragraph:/^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/, +text:/^[^\n]+/};block.bullet=/(?:[*+-]|\d+\.)/;block.item=/^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;block.item=replace(block.item,"gm")(/bull/g,block.bullet)();block.list=replace(block.list)(/bull/g,block.bullet)("hr",/\n+(?=(?: *[-*_]){3,} *(?:\n+|$))/)();block._tag="(?!(?:"+"a|em|strong|small|s|cite|q|dfn|abbr|data|time|code"+"|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo"+"|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|@)\\b";block.html=replace(block.html)("comment",/\x3c!--[\s\S]*?--\x3e/)("closed", +/<(tag)[\s\S]+?<\/\1>/)("closing",/])*?>/)(/tag/g,block._tag)();block.paragraph=replace(block.paragraph)("hr",block.hr)("heading",block.heading)("lheading",block.lheading)("blockquote",block.blockquote)("tag","<"+block._tag)("def",block.def)();block.normal=merge({},block);block.gfm=merge({},block.normal,{fences:/^ *(`{3,}|~{3,}) *(\S+)? *\n([\s\S]+?)\s*\1 *(?:\n+|$)/,paragraph:/^/});block.gfm.paragraph=replace(block.paragraph)("(?!","(?!"+block.gfm.fences.source.replace("\\1", +"\\2")+"|")();block.tables=merge({},block.gfm,{nptable:/^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,table:/^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/});function Lexer(options){this.tokens=[];this.tokens.links={};this.options=options||marked.defaults;this.rules=block.normal;if(this.options.gfm)if(this.options.tables)this.rules=block.tables;else this.rules=block.gfm}Lexer.rules=block;Lexer.lex=function(src,options){var lexer=new Lexer(options);return lexer.lex(src)}; +Lexer.prototype.lex=function(src){src=src.replace(/\r\n|\r/g,"\n").replace(/\t/g," ").replace(/\u00a0/g," ").replace(/\u2424/g,"\n");return this.token(src,true)};Lexer.prototype.token=function(src,top){var src=src.replace(/^ +$/gm,""),next,loose,cap,bull,b,item,space,i,l;while(src){if(cap=this.rules.newline.exec(src)){src=src.substring(cap[0].length);if(cap[0].length>1)this.tokens.push({type:"space"})}if(cap=this.rules.code.exec(src)){src=src.substring(cap[0].length);cap=cap[0].replace(/^ {4}/gm, +"");this.tokens.push({type:"code",text:!this.options.pedantic?cap.replace(/\n+$/,""):cap});continue}if(cap=this.rules.fences.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"code",lang:cap[2],text:cap[3]});continue}if(cap=this.rules.heading.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"heading",depth:cap[1].length,text:cap[2]});continue}if(top&&(cap=this.rules.nptable.exec(src))){src=src.substring(cap[0].length);item={type:"table",header:cap[1].replace(/^ *| *\| *$/g, +"").split(/ *\| */),align:cap[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:cap[3].replace(/\n$/,"").split("\n")};for(i=0;i ?/gm,"");this.token(cap,top);this.tokens.push({type:"blockquote_end"});continue}if(cap=this.rules.list.exec(src)){src=src.substring(cap[0].length); +bull=cap[2];this.tokens.push({type:"list_start",ordered:bull.length>1});cap=cap[0].match(this.rules.item);next=false;l=cap.length;i=0;for(;i1&&b.length>1)){src=cap.slice(i+ +1).join("\n")+src;i=l-1}}loose=next||/\n\n(?!\s*$)/.test(item);if(i!==l-1){next=item[item.length-1]==="\n";if(!loose)loose=next}this.tokens.push({type:loose?"loose_item_start":"list_item_start"});this.token(item,false);this.tokens.push({type:"list_item_end"})}this.tokens.push({type:"list_end"});continue}if(cap=this.rules.html.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:this.options.sanitize?"paragraph":"html",pre:cap[1]==="pre"||cap[1]==="script",text:cap[0]});continue}if(top&& +(cap=this.rules.def.exec(src))){src=src.substring(cap[0].length);this.tokens.links[cap[1].toLowerCase()]={href:cap[2],title:cap[3]};continue}if(top&&(cap=this.rules.table.exec(src))){src=src.substring(cap[0].length);item={type:"table",header:cap[1].replace(/^ *| *\| *$/g,"").split(/ *\| */),align:cap[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:cap[3].replace(/(?: *\| *)?\n$/,"").split("\n")};for(i=0;i])/,autolink:/^<([^ >]+(@|:\/)[^ >]+)>/,url:noop,tag:/^\x3c!--[\s\S]*?--\x3e|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,link:/^!?\[(inside)\]\(href\)/,reflink:/^!?\[(inside)\]\s*\[([^\]]*)\]/,nolink:/^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,strong:/^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,em:/^\b_((?:__|[\s\S])+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/, +code:/^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,br:/^ {2,}\n(?!\s*$)/,del:noop,text:/^[\s\S]+?(?=[\\?(?:\s+['"]([\s\S]*?)['"])?\s*/;inline.link=replace(inline.link)("inside",inline._inside)("href",inline._href)();inline.reflink=replace(inline.reflink)("inside",inline._inside)();inline.normal=merge({},inline);inline.pedantic=merge({},inline.normal,{strong:/^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/, +em:/^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/});inline.gfm=merge({},inline.normal,{escape:replace(inline.escape)("])","~|])")(),url:/^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,del:/^~~(?=\S)([\s\S]*?\S)~~/,text:replace(inline.text)("]|","~]|")("|","|https?://|")()});inline.breaks=merge({},inline.gfm,{br:replace(inline.br)("{2,}","*")(),text:replace(inline.gfm.text)("{2,}","*")()});function InlineLexer(links,options){this.options=options||marked.defaults;this.links=links;this.rules=inline.normal; +if(!this.links)throw new Error("Tokens array requires a `links` property.");if(this.options.gfm)if(this.options.breaks)this.rules=inline.breaks;else this.rules=inline.gfm;else if(this.options.pedantic)this.rules=inline.pedantic}InlineLexer.rules=inline;InlineLexer.output=function(src,links,options){var inline=new InlineLexer(links,options);return inline.output(src)};InlineLexer.prototype.output=function(src){var out="",link,text,href,cap;while(src){if(cap=this.rules.escape.exec(src)){src=src.substring(cap[0].length); +out+=cap[1];continue}if(cap=this.rules.autolink.exec(src)){src=src.substring(cap[0].length);if(cap[2]==="@"){text=cap[1][6]===":"?this.mangle(cap[1].substring(7)):this.mangle(cap[1]);href=this.mangle("mailto:")+text}else{text=escape(cap[1]);href=text}out+=''+text+"";continue}if(cap=this.rules.url.exec(src)){src=src.substring(cap[0].length);text=escape(cap[1]);href=text;out+=''+text+"";continue}if(cap=this.rules.tag.exec(src)){src=src.substring(cap[0].length); +out+=this.options.sanitize?escape(cap[0]):cap[0];continue}if(cap=this.rules.link.exec(src)){src=src.substring(cap[0].length);out+=this.outputLink(cap,{href:cap[2],title:cap[3]});continue}if((cap=this.rules.reflink.exec(src))||(cap=this.rules.nolink.exec(src))){src=src.substring(cap[0].length);link=(cap[2]||cap[1]).replace(/\s+/g," ");link=this.links[link.toLowerCase()];if(!link||!link.href){out+=cap[0][0];src=cap[0].substring(1)+src;continue}out+=this.outputLink(cap,link);continue}if(cap=this.rules.strong.exec(src)){src= +src.substring(cap[0].length);out+=""+this.output(cap[2]||cap[1])+"";continue}if(cap=this.rules.em.exec(src)){src=src.substring(cap[0].length);out+=""+this.output(cap[2]||cap[1])+"";continue}if(cap=this.rules.code.exec(src)){src=src.substring(cap[0].length);out+=""+escape(cap[2],true)+"";continue}if(cap=this.rules.br.exec(src)){src=src.substring(cap[0].length);out+="
    ";continue}if(cap=this.rules.del.exec(src)){src=src.substring(cap[0].length);out+=""+ +this.output(cap[1])+"";continue}if(cap=this.rules.text.exec(src)){src=src.substring(cap[0].length);out+=escape(cap[0]);continue}if(src)throw new Error("Infinite loop on byte: "+src.charCodeAt(0));}return out};InlineLexer.prototype.outputLink=function(cap,link){if(cap[0][0]!=="!")return'"+this.output(cap[1])+"";else return''+escape(cap[1])+'"};InlineLexer.prototype.smartypants=function(text){if(!this.options.smartypants)return text;return text.replace(/--/g,"\u2014").replace(/'([^']*)'/g,"\u2018$1\u2019").replace(/"([^"]*)"/g,"\u201c$1\u201d").replace(/\.{3}/g,"\u2026")};InlineLexer.prototype.mangle=function(text){var out="",l=text.length,i=0,ch;for(;i0.5)ch="x"+ch.toString(16);out+="&#"+ch+";"}return out};function Parser(options){this.tokens=[];this.token=null; +this.options=options||marked.defaults}Parser.parse=function(src,options){var parser=new Parser(options);return parser.parse(src)};Parser.prototype.parse=function(src){this.inline=new InlineLexer(src.links,this.options);this.tokens=src.reverse();var out="";while(this.next())out+=this.tok();return out};Parser.prototype.next=function(){return this.token=this.tokens.pop()};Parser.prototype.peek=function(){return this.tokens[this.tokens.length-1]||0};Parser.prototype.parseText=function(){var body=this.token.text; +while(this.peek().type==="text")body+="\n"+this.next().text;return this.inline.output(body)};Parser.prototype.tok=function(){switch(this.token.type){case "space":return"";case "hr":return"
    \n";case "heading":return""+this.inline.output(this.token.text)+"\n";case "code":if(this.options.highlight){var code=this.options.highlight(this.token.text,this.token.lang);if(code!=null&&code!==this.token.text){this.token.escaped=true;this.token.text=code}}if(!this.token.escaped)this.token.text= +escape(this.token.text,true);return"
    "+this.token.text+"
    \n";case "table":var body="",heading,i,row,cell,j;body+="\n\n";for(i=0;i'+heading+"\n":""+heading+"\n"}body+="\n\n";body+="\n";for(i=0;i'+cell+"\n":""+cell+"\n"}body+="\n"}body+="\n";return"\n"+body+"
    \n";case "blockquote_start":var body="";while(this.next().type!=="blockquote_end")body+=this.tok();return"
    \n"+body+"
    \n";case "list_start":var type=this.token.ordered?"ol":"ul",body="";while(this.next().type!=="list_end")body+= +this.tok();return"<"+type+">\n"+body+"\n";case "list_item_start":var body="";while(this.next().type!=="list_item_end")body+=this.token.type==="text"?this.parseText():this.tok();return"
  • "+body+"
  • \n";case "loose_item_start":var body="";while(this.next().type!=="list_item_end")body+=this.tok();return"
  • "+body+"
  • \n";case "html":return!this.token.pre&&!this.options.pedantic?this.inline.output(this.token.text):this.token.text;case "paragraph":return"

    "+this.inline.output(this.token.text)+ +"

    \n";case "text":return"

    "+this.parseText()+"

    \n"}};function escape(html,encode){return html.replace(!encode?/&(?!#?\w+;)/g:/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}function replace(regex,opt){regex=regex.source;opt=opt||"";return function self(name,val){if(!name)return new RegExp(regex,opt);val=val.source||val;val=val.replace(/(^|[^\[])\^/g,"$1");regex=regex.replace(name,val);return self}}function noop(){}noop.exec=noop;function merge(obj){var i= +1,target,key;for(;iAn error occured:

    "+escape(e.message+"",true)+"
    ";throw e;}}marked.options=marked.setOptions=function(opt){merge(marked.defaults,opt);return marked};marked.defaults={gfm:true,tables:true,breaks:false,pedantic:false,sanitize:false,smartLists:false,silent:false,highlight:null,langPrefix:""};marked.Parser=Parser;marked.parser=Parser.parse;marked.Lexer=Lexer;marked.lexer=Lexer.lex;marked.InlineLexer=InlineLexer;marked.inlineLexer=InlineLexer.output; +marked.parse=marked;if(typeof exports==="object")module.exports=marked;else if(typeof define==="function"&&define.amd)define(function(){return marked});else this.marked=marked}).call(function(){return this||(typeof window!=="undefined"?window:global)}()); diff --git a/asm-talk/plugin/notes/notes.html b/asm-talk/plugin/notes/notes.html new file mode 100644 index 0000000..b91fbb7 --- /dev/null +++ b/asm-talk/plugin/notes/notes.html @@ -0,0 +1,263 @@ + + + + + + reveal.js - Slide Notes + + + + + + +
    + +
    + +
    + + UPCOMING: +
    + +
    +
    +

    Time

    + 0:00:00 AM +
    +
    +

    Elapsed

    + 00:00:00 +
    +
    + +
    + + + + + \ No newline at end of file diff --git a/asm-talk/plugin/notes/notes.js b/asm-talk/plugin/notes/notes.js new file mode 100644 index 0000000..63de05a --- /dev/null +++ b/asm-talk/plugin/notes/notes.js @@ -0,0 +1,100 @@ +/** + * Handles opening of and synchronization with the reveal.js + * notes window. + */ +var RevealNotes = (function() { + + function openNotes() { + var jsFileLocation = document.querySelector('script[src$="notes.js"]').src; // this js file path + jsFileLocation = jsFileLocation.replace(/notes\.js(\?.*)?$/, ''); // the js folder path + var notesPopup = window.open( jsFileLocation + 'notes.html', 'reveal.js - Notes', 'width=1120,height=850' ); + + // Fires when slide is changed + Reveal.addEventListener( 'slidechanged', function( event ) { + post('slidechanged'); + } ); + + // Fires when a fragment is shown + Reveal.addEventListener( 'fragmentshown', function( event ) { + post('fragmentshown'); + } ); + + // Fires when a fragment is hidden + Reveal.addEventListener( 'fragmenthidden', function( event ) { + post('fragmenthidden'); + } ); + + /** + * Posts the current slide data to the notes window + * + * @param {String} eventType Expecting 'slidechanged', 'fragmentshown' + * or 'fragmenthidden' set in the events above to define the needed + * slideDate. + */ + function post( eventType ) { + var slideElement = Reveal.getCurrentSlide(), + messageData; + + if( eventType === 'slidechanged' ) { + var notes = slideElement.querySelector( 'aside.notes' ), + indexh = Reveal.getIndices().h, + indexv = Reveal.getIndices().v, + nextindexh, + nextindexv; + + if( slideElement.nextElementSibling && slideElement.parentNode.nodeName == 'SECTION' ) { + nextindexh = indexh; + nextindexv = indexv + 1; + } else { + nextindexh = indexh + 1; + nextindexv = 0; + } + + messageData = { + notes : notes ? notes.innerHTML : '', + indexh : indexh, + indexv : indexv, + nextindexh : nextindexh, + nextindexv : nextindexv, + markdown : notes ? typeof notes.getAttribute( 'data-markdown' ) === 'string' : false + }; + } + else if( eventType === 'fragmentshown' ) { + messageData = { + fragment : 'next' + }; + } + else if( eventType === 'fragmenthidden' ) { + messageData = { + fragment : 'prev' + }; + } + + notesPopup.postMessage( JSON.stringify( messageData ), '*' ); + } + + // Navigate to the current slide when the notes are loaded + notesPopup.addEventListener( 'load', function( event ) { + post('slidechanged'); + }, false ); + } + + // If the there's a 'notes' query set, open directly + if( window.location.search.match( /(\?|\&)notes/gi ) !== null ) { + openNotes(); + } + + // Open the notes when the 's' key is hit + document.addEventListener( 'keydown', function( event ) { + // Disregard the event if the target is editable or a + // modifier is present + if ( document.querySelector( ':focus' ) !== null || event.shiftKey || event.altKey || event.ctrlKey || event.metaKey ) return; + + if( event.keyCode === 83 ) { + event.preventDefault(); + openNotes(); + } + }, false ); + + return { open: openNotes }; +})(); diff --git a/asm-talk/plugin/zoom-js/zoom.js b/asm-talk/plugin/zoom-js/zoom.js new file mode 100644 index 0000000..b67ae16 --- /dev/null +++ b/asm-talk/plugin/zoom-js/zoom.js @@ -0,0 +1,256 @@ +// Custom reveal.js integration +(function(){ + var isEnabled = true; + + document.querySelector( '.reveal' ).addEventListener( 'mousedown', function( event ) { + if( event.altKey && isEnabled ) { + event.preventDefault(); + zoom.to({ element: event.target, pan: false }); + } + } ); + + Reveal.addEventListener( 'overviewshown', function() { isEnabled = false; } ); + Reveal.addEventListener( 'overviewhidden', function() { isEnabled = true; } ); +})(); + +/*! + * zoom.js 0.2 (modified version for use with reveal.js) + * http://lab.hakim.se/zoom-js + * MIT licensed + * + * Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se + */ +var zoom = (function(){ + + // The current zoom level (scale) + var level = 1; + + // The current mouse position, used for panning + var mouseX = 0, + mouseY = 0; + + // Timeout before pan is activated + var panEngageTimeout = -1, + panUpdateInterval = -1; + + var currentOptions = null; + + // Check for transform support so that we can fallback otherwise + var supportsTransforms = 'WebkitTransform' in document.body.style || + 'MozTransform' in document.body.style || + 'msTransform' in document.body.style || + 'OTransform' in document.body.style || + 'transform' in document.body.style; + + if( supportsTransforms ) { + // The easing that will be applied when we zoom in/out + document.body.style.transition = 'transform 0.8s ease'; + document.body.style.OTransition = '-o-transform 0.8s ease'; + document.body.style.msTransition = '-ms-transform 0.8s ease'; + document.body.style.MozTransition = '-moz-transform 0.8s ease'; + document.body.style.WebkitTransition = '-webkit-transform 0.8s ease'; + } + + // Zoom out if the user hits escape + document.addEventListener( 'keyup', function( event ) { + if( level !== 1 && event.keyCode === 27 ) { + zoom.out(); + } + }, false ); + + // Monitor mouse movement for panning + document.addEventListener( 'mousemove', function( event ) { + if( level !== 1 ) { + mouseX = event.clientX; + mouseY = event.clientY; + } + }, false ); + + /** + * Applies the CSS required to zoom in, prioritizes use of CSS3 + * transforms but falls back on zoom for IE. + * + * @param {Number} pageOffsetX + * @param {Number} pageOffsetY + * @param {Number} elementOffsetX + * @param {Number} elementOffsetY + * @param {Number} scale + */ + function magnify( pageOffsetX, pageOffsetY, elementOffsetX, elementOffsetY, scale ) { + + if( supportsTransforms ) { + var origin = pageOffsetX +'px '+ pageOffsetY +'px', + transform = 'translate('+ -elementOffsetX +'px,'+ -elementOffsetY +'px) scale('+ scale +')'; + + document.body.style.transformOrigin = origin; + document.body.style.OTransformOrigin = origin; + document.body.style.msTransformOrigin = origin; + document.body.style.MozTransformOrigin = origin; + document.body.style.WebkitTransformOrigin = origin; + + document.body.style.transform = transform; + document.body.style.OTransform = transform; + document.body.style.msTransform = transform; + document.body.style.MozTransform = transform; + document.body.style.WebkitTransform = transform; + } + else { + // Reset all values + if( scale === 1 ) { + document.body.style.position = ''; + document.body.style.left = ''; + document.body.style.top = ''; + document.body.style.width = ''; + document.body.style.height = ''; + document.body.style.zoom = ''; + } + // Apply scale + else { + document.body.style.position = 'relative'; + document.body.style.left = ( - ( pageOffsetX + elementOffsetX ) / scale ) + 'px'; + document.body.style.top = ( - ( pageOffsetY + elementOffsetY ) / scale ) + 'px'; + document.body.style.width = ( scale * 100 ) + '%'; + document.body.style.height = ( scale * 100 ) + '%'; + document.body.style.zoom = scale; + } + } + + level = scale; + + if( level !== 1 && document.documentElement.classList ) { + document.documentElement.classList.add( 'zoomed' ); + } + else { + document.documentElement.classList.remove( 'zoomed' ); + } + } + + /** + * Pan the document when the mosue cursor approaches the edges + * of the window. + */ + function pan() { + var range = 0.12, + rangeX = window.innerWidth * range, + rangeY = window.innerHeight * range, + scrollOffset = getScrollOffset(); + + // Up + if( mouseY < rangeY ) { + window.scroll( scrollOffset.x, scrollOffset.y - ( 1 - ( mouseY / rangeY ) ) * ( 14 / level ) ); + } + // Down + else if( mouseY > window.innerHeight - rangeY ) { + window.scroll( scrollOffset.x, scrollOffset.y + ( 1 - ( window.innerHeight - mouseY ) / rangeY ) * ( 14 / level ) ); + } + + // Left + if( mouseX < rangeX ) { + window.scroll( scrollOffset.x - ( 1 - ( mouseX / rangeX ) ) * ( 14 / level ), scrollOffset.y ); + } + // Right + else if( mouseX > window.innerWidth - rangeX ) { + window.scroll( scrollOffset.x + ( 1 - ( window.innerWidth - mouseX ) / rangeX ) * ( 14 / level ), scrollOffset.y ); + } + } + + function getScrollOffset() { + return { + x: window.scrollX !== undefined ? window.scrollX : window.pageXOffset, + y: window.scrollY !== undefined ? window.scrollY : window.pageXYffset + } + } + + return { + /** + * Zooms in on either a rectangle or HTML element. + * + * @param {Object} options + * - element: HTML element to zoom in on + * OR + * - x/y: coordinates in non-transformed space to zoom in on + * - width/height: the portion of the screen to zoom in on + * - scale: can be used instead of width/height to explicitly set scale + */ + to: function( options ) { + // Due to an implementation limitation we can't zoom in + // to another element without zooming out first + if( level !== 1 ) { + zoom.out(); + } + else { + options.x = options.x || 0; + options.y = options.y || 0; + + // If an element is set, that takes precedence + if( !!options.element ) { + // Space around the zoomed in element to leave on screen + var padding = 20; + + options.width = options.element.getBoundingClientRect().width + ( padding * 2 ); + options.height = options.element.getBoundingClientRect().height + ( padding * 2 ); + options.x = options.element.getBoundingClientRect().left - padding; + options.y = options.element.getBoundingClientRect().top - padding; + } + + // If width/height values are set, calculate scale from those values + if( options.width !== undefined && options.height !== undefined ) { + options.scale = Math.max( Math.min( window.innerWidth / options.width, window.innerHeight / options.height ), 1 ); + } + + if( options.scale > 1 ) { + options.x *= options.scale; + options.y *= options.scale; + + var scrollOffset = getScrollOffset(); + + if( options.element ) { + scrollOffset.x -= ( window.innerWidth - ( options.width * options.scale ) ) / 2; + } + + magnify( scrollOffset.x, scrollOffset.y, options.x, options.y, options.scale ); + + if( options.pan !== false ) { + + // Wait with engaging panning as it may conflict with the + // zoom transition + panEngageTimeout = setTimeout( function() { + panUpdateInterval = setInterval( pan, 1000 / 60 ); + }, 800 ); + + } + } + + currentOptions = options; + } + }, + + /** + * Resets the document zoom state to its default. + */ + out: function() { + clearTimeout( panEngageTimeout ); + clearInterval( panUpdateInterval ); + + var scrollOffset = getScrollOffset(); + + if( currentOptions && currentOptions.element ) { + scrollOffset.x -= ( window.innerWidth - ( currentOptions.width * currentOptions.scale ) ) / 2; + } + + magnify( scrollOffset.x, scrollOffset.y, 0, 0, 1 ); + + level = 1; + }, + + // Alias + magnify: function( options ) { this.to( options ) }, + reset: function() { this.out() }, + + zoomLevel: function() { + return level; + } + } + +})(); + diff --git a/asm-talk/talking_notes.txt b/asm-talk/talking_notes.txt new file mode 100644 index 0000000..ba22d79 --- /dev/null +++ b/asm-talk/talking_notes.txt @@ -0,0 +1,230 @@ +asm talk notes: + +Hi everyone, thanks for coming. Today I’m going to talk a bit about creating a fibonacci number generator in assembly language. + +I’m currently a Systems Engineer in GDE, at least for the next few days but thought i’d share a project I’ve been working on in my spare time. + +So who here has done any work in assembly language before? Yes/No? Cool! +Well, I decided to teach myself Assembly after having not touched it many years ago at University. + +The first question that may come to mind it why? +What would possess you to learn assembly language? +Everything is in high-level languages these days. +Like, there must be a really good reason for wanting to learn it, yeah? +Well as my role as a systems engineer and having been a developer for many years before that, I wanted to know the fundamentals of both how other languages work, improve my troubleshooting skills and improve my security chops. +Sometimes as a systems engineer you’d come across memory leaks or processes that have core dumped and it would be good to know what has caused a system to get into a certain state. +As well, in my spare time I do crypto mining and want to know how GPUs work at their core to improve the efficiency of the algorithms running on them. And learning assembly seemed to cover all these bases. + +So I got started by reading a few books, defining a small by challenging project, started implementing the project and used online resources to overcome any issues that arose. + +So after reading a few books on the topic, the small project of creating a fibonacci generator involved reading input from the command line as a string of numbers, finding the length of the string, converting the string to to a decimal number, generating the fibonacci number from the input number and printing the result to the screen. + +But there were a few decisions to be made. +The first turned out to be the most important as to whether to use the standard glibc linux library. +The glibc library has a lot of string manipulation functions that make developer’s life easier, especially when dealing with assembly, but I decided to do everything from scratch as it would help me learn the subject domain better. +The second choice was what variant of assembly language to go with. +There are a few different flavours out there but I decided on GAS, the GNU Assembler as it is also used by gcc, when compiling C code, is cross-platform and I personally found easier to read than other assembly languages. +The last choice was whether it would be 32 or 64 bit. +I went with 32 bit as it was not as steep a learning curve and my two main resources on were in 32 bit as well. + +So, who knows what the fibonacci sequence is? Yep, cool. + +Ok, so just to recap, the sequence is where for a given number, it’s value is the sum of the two values immediately preceding it in the sequence. It’s usually seeded with the numbers 0, 1, 1 so that the first number of the sequence is 2, 3, 5, and so on. + +A sequence would look something like this. +With positional values like this. +So our fibonacci generator would take in a positional value and return us the corresponding fibonacci number. + +At it’s core, it would look something like this. +There are many ways to generate fibonacci numbers but I chose this one as it is easy to understand and implement, wasn’t a reentrant function and didn’t use complex data types like 2-dimensional arrays. +It was also reasonably efficient in time and space complexity. + +So we’re almost ready to dive into the implementation, but before I do, there’s some starting knowledge required in order to grasp what’s going on. + +Firstly, that GAS assembler uses .s files for source code. +Usually there are many such files used in a project but for simplicity I’ve limited it to one file per version of the implementation. +We can see here the .section .text line at the top. +In a GAS file, there are three sections. .text is for our code, .data is for any initialised variables and .bss is for any uninitialised variables. +For this project we are only concerned with the .text section as we don’t store any data in our binary or share complex data types between functions. +Then there’s the 'globl .start' which is similar to node or react where we can export code for use in other files. +It specifies the label of the code to export and is essentially an entry point into the code from other files when binary object files are linked together. +Under that is the _start: label that defines an address in the code. +It is essentially this address that is exposed by the globl line. +Every linux executable will have a start label to indicate to the launcher where to start executing code. +On windows the main label is used for the same purpose. +Following that we have some instructions and a comment in the middle. +The instructions are called opcodes and can have multiple operands applied to them. Most have one or two operands, a lot less have 3 or 4 operands. +So, this code effectively does nothing. But more importantly doesn’t crash or segfault the process. + +These opcodes and operands are effectively the building blocks for making a process do something in assembly. I’ll just briefly go through what they do here. +We can see here different instructions and varying numbers of operands. + +In order to assemble our source code into an executable, we first use the as assembler which produces an object file. This object file is just a group of binary instructions. +A linker, ld is then used to resolve any dependencies and convert our object file into an ELF executable. +This defines the text, data and bss sections, specifies the entrypoint and specifies other information about the executable, like whether it’s 32 or 64 bit, versioning and other metadata. + +There are also a few other tools that are useful when building binaries and/or reversing them, such as nm that outputs the sections of the file, objdump and elf dump that can disassemble and give more detailed information. There’s also gdb that can be used for debugging, which I’ll show in a moment, as well as gcc and make. + +It’s important to know that at the core of a cpu, there’s the ALU that does the processing, and the registers that store temporary values for very quick access. +There’s also the memory system that is further away from the cpu and takes longer to access. + +While accessing a register may take 1 or 2 cpu clock cycles, accessing memory may take a few hundred clock cycles. +Hard disk access can take many tens or hundreds of thousands to millions of clock cycles, and so on where the further from the cpu the data is, the higher the latency. + +The registers on a 32 bit cpu are categorised into general purpose, index and pointer registers. +We’ve got EAX, to EDX which are general purpose, and be referenced for smaller operations by for example AH, AL and AX for 8, 8 and 16 bits respectively. +ESI and EDI are usually used for doing memory operations that require an index into a sequence of bytes. +And there’s also ESP, EBP and EIP (not pictured) that are used to control program flow. + +Just coming back to our trivial example before, I’ll briefly describe what the instructions in it are and how they work. +The first was nop, which is a no-operation and is more of a filler that anything else. +It used to be used more on older cpus that didn’t have pipelining but is less useful these days unless patching binaries and needing to fill space. + +Probably the most important opcode is the MOV. +It copies a chunk of data to and from memory and registers and allows placing immediate, or fixed values into registers and memory. +Most combinations are possible except memory to memory and anything into a fixed value for obvious reasons. (Describe examples). + +MOV has different variations based on the size of data to copy, In our 32 bit world where we’re not doing floating point operations, we’re mainly interested in values up to 32 bits. + +Another very important instruction is INT. +It is used for calling from user space into the kernel through what is called a ‘soft interrupt’. +Most interrupts are hardware based for device drivers, the system clock and other things, but applications use this to request privileged functions of the kernel. +Things like reading and writing to disk, allocating memory, and so on. +The 0x80 is important as the linux kernel has an interrupt vector table that looks up what kernel function to call, in conjunction with the registers set, to determine what the kernel should do for the request. +(Describe example). +It’s important to note that modern cpus implement the SYSCALL opcode that is different in usage and is quicker, but INT instructions are still valid. + +Great, so we’ve got some background info out of the way, we can start on our implementation. + +But before we do, the first thing to do in getting the argument from the command line is to understand the stack, as all command line arguments and environment variables are placed on the stack when our app is launched. +Each process has it’s own stack space when launched and it’s address space is both virtualised and randomised, but the virtualisation makes it appear to the process that it has full access to all memory on the system. +We can see in the diagram that the stack is at the top of memory and grows downwards and we have our text, data and bss sections at the bottom, then our heap (which we’re not using). + +This table essentially shows that there are pointers to strings in memory that contain values for our command line arguments and for environment variables. +It doesn’t contain the data at these locations but rather the locations in memory where these strings are stored. + +To use this in a trivial example that just prints the first 4 characters of the first command line argument, we could do something like the following. In the first section we’re taking a copy of our stack pointer into ebp adding 8 to it’s value then copying the address pointed to by this new address into ecx. +Note the brackets around ebp here mean that this is copying from memory and not the actual value of ebp. +This is the starting point of the command line string argument. +The second section prepares for an interrupt call, but this time it’s not an exit call, but to tell the kernel to write to file. +This is determined by eax=4, where for an exit it would be eax=1. + +I’ll now quickly show you how this works in the gdb debugger. + +gas-asm-fib +./docker-shell +gdb --args ./fib2 test +list +b 5 +r +info registers +stepi up to line 10 +x/5s ($ecx) +c +q + +Ok, so that’s great if we have a fixed size number from the command line, but it’s not really useful for where we have varying size input from the command line. +We basically hardcoded it in the last example, so the next step is to determine the size of the string we are working with. +This part actually wasn’t required for the implementation I later realised but it is useful for highlighting some assembly principles, nonetheless so I’ll still go through it for completeness. + +The approach here is to basically get the first command line argument, get the length of the string and print it to standard out. + +This is the full implementation here and you’ll notice that in the middle we have some extra code to get the length of the string. + +Effectively this chunk of code here. +You’ll notice some new instructions here like push and pop, cld, subl and repne scasb. +Push and pop are used to store and retrieve values from our stack. +Because there are very few registers to use, we do this when we need to reuse a register for another operation and then retrieve the stored value for use at a later time. +As calls to memory are expensive on clock cycles, we tend to avoid doing it if it can be helped. +EDI is placed on the stack here as a precaution as repne scasb clobbers it, but we’re not actually using EDI for anything else so isn’t all that necessary. +The key instruction here is repne scasb which works similar to our INT calls previously and requires registers to be set up before use. +REPNE SCASB effectively scans a string in memory for a value in our EAX register and decrements ECX for every byte traversed that doesn’t contain it. +We’re initially setting ECX to a high value, 50 in this case, so that our count doesn’t go negative as the scan will also stop if ECX reaches zero. +We also take a copy of this high value for calculating the length later. + +Our command line arguments are null terminated with a zero byte, and so if we scan for that zero value, while counting down in ECX, we should be able to determine the length of the string. + +So after the scacb loop finishes, we have 50 minus the length of our string plus 1. +The plus 1 is because the zero byte is included in our string length and is not part of the string length. +After refactoring this equation, we want to subtract our count ECX from the original value of 50 in EBX, which is what the subl instruction does, then decrease it by 1 for the null byte. + +So the next thing that really helps is to be able to refactor this into separate functions using labels. +This greatly improves readability and flow of the code. +Labels as mentioned earlier just point to a location in memory and are resolved with our linker. +There’s two types of labels - standard labels and local labels. +The only difference is that local labels start with a dot and are local to a file. +This is useful when using multiple source files so that labels don’t collide. + +Labels are used with CALL and RET instructions where a CALL will take a copy of the next instruction from EIP, the instruction pointer, to run onto the stack, change program execution to the address of the label and continue processing. +RET is the opposite where it grabs the last address on the stack and makes it the address of the next instruction to run in EIP. + +As a simple example we can see here of calling a label and returning from it. + +In effect, this gives us this implementation here that is much easier to read. + +The next thing to do is convert our string into a number, as the input from the command line is a string of characters representing a number, not actually a number. + +In pseudo C code, it would look something like this, where we get a pointer to an array of characters, iterate over those numbers to determine it is a valid number, convert the characters to a decimal number at a certain position and repeat the process. +As the order of processing is from most significant to least significant digit, we multiply the intermediate value by 10 each time to shuffle all our digits across by 1 place. +When we reach a non-number, we stop the loop and return the result. + +The implementation of this here introduces a few more new instructions/opcodes like XOR, INC, CMPB, JL, JG, JL, SUB and IMUL. +In addition we’re using CL, which is the 8-bit subset of the 32 bit ECX. +One other thing to notice is the $47 and $58 values which indicate the ASCII values for 0 and 9 respectively. + +These are sequential on the ASCII table and so we can use that to exclude non-digit characters from our function. + +There’s quite a lot going on here, but the important thing to note is that a loop is formed in our code that is conditional on the string it is reading in memory. +One other register that I haven’t described up to now is the EFLAGS register that holds a heap of information about the last instruction. +When a CMP, or comparison operation executes, it sets these flags based on the result. +The Jump flags can then use these to conditionally jump to a label based on the results of the comparison. There’s a list of them here but there are a lot more, and all have specific criteria depending on the value of the flags set. + +At this point I’m hoping you can start to see how these primitives may be able to be used to create higher-level programming languages with structured programming constructs like if/else, for, while and when loops, because in essence, this is how they work ‘under the hood. + +Ok, so now we're at the actual implementation of creating a fibonacci number. +I find it useful to put input, processing and ouptut comments at the top of functions so when coming back to code days, weeks or months later, it's evident exactly what it's doing, what registers or stack state is expected as input, and what registers and stacks hold the output. +We can see here that the input for this function is EAX that holds the Fibonacci Number to generate for and it returns the result in EBX. +When dealing with a very terse language like assembly language, it becomes very important to use comments. +In some other languages, comments are almost an anti-pattern but in assembly its a necessity. +There are essentially two parts to this function, the first part is setting up the variables and the stack, and the second is the core logic of the implementation. + +Coming back to our C implementation, we can see the same thing with variable initialisation and our for loop. EAX would be the variable n and the return value f[n] would be EBX. + +This is the variable initialisation here. +The first t lines preserve our stack pointer with ESP and EBP. +The next four lines preserve our stack space for the array and the last 5 lines initialise the array with the values 0 and 1 in the first two positions and increment our array counter twice. + +When the stack is used in a function, the value of ESP changes. +As we have called into this function, when we call ret at the end of our function it expects the stack pointer to point to the return address of the code that called it so it can continue processing. +That's why we push EBP to the stack and take a copy of ESP into EBP. +We're then free to use esp locally for aour array before restoring ESP from EBP and restoring the value of EBP from the stack. +It's done this way instead of just pushing ESP onto the stack as it is a lot safer than using the stack to store the stack pointer. + +To initialise our array on the stack, we get our array size in EBX and multiply it by 4. +This is what the SHL opcode does. +It effectively shifts all the bits in the register to the left by two which is the sme as multiplying by 4. +The reason it's multiplied by 4 is that we are using the long data type which is 32 bits and each memory address references 1 byte, or 8 bits. +The subl instruction then takes the full memory size of the array and subtracts that from the current stack pointer. +The reason it is a subtract and not an addition is that our stack grows downward and new memory allocation starts from higher addresses to lower addresses. + +Before we get to the core implementation of Fibonacci, there's a thing with MOV instructions called indexed memory. +This effectively allows us to read and write to memory in a more advanced way to access different data types. +The general rule is that we have our absolute offset, which is usually ESP followed by our index and the size of our index. A second relative offet is also alloed for additional flexibility. + +So if we now look at the core of the implementation, we can see two jumps. +The first jumps out of the loop if our iterator has reached the number of iterations required. +The second jump is unconditional and just iterates the loop. +What is happening inside the loop is that we copy the n-1 value into EBX, the n-2 value into EDX, add them together and move the result into the currently indexed memory location. +We then increase our counter and repeat the loop. +When we're done, EBX has our final result, we can release the stack memory and return to the main execution of our application. + +The next function essentially converts our decimal number back to a string and prints it to the screen. + +Here is the code for it. + +But for brevity I'll just explain it quickly. + +Conclusion. + + + diff --git a/docker-shell b/docker-shell index d5f3788..912dc3c 100755 --- a/docker-shell +++ b/docker-shell @@ -1,3 +1,7 @@ #!/bin/bash -docker run -it -v $PWD:/gas-asm-fib --security-opt seccomp=unconfined --workdir=/gas-asm-fib tomerbd/gcc-gdb-dockerfile bash +CURRENT_PATH=${PWD##*/} +DOCKER_IMAGE_NAME=$CURRENT_PATH + +docker build -t ${DOCKER_IMAGE_NAME} . +docker run -it -v $PWD:/$CURRENT_PATH --security-opt seccomp=unconfined --workdir=/$CURRENT_PATH ${DOCKER_IMAGE_NAME} bash