colorful rat Ratfactor.com > Dave's Repos

meow5

A stack-based pure inlining concatenative programming language written in NASM assembly
git clone http://ratfactor.com/repos/meow5/meow5.git

meow5/log01.txt

Download raw file: log01.txt

1 First log! I've spent a couple weeks setting up the 2 basic environment. Much of my time has been in the 3 excellent tmux man page. 4 5 The biggest thing has been having a Bash alias that 6 starts up my dev environment for the project. That was 7 actually a little tricky. 8 The key here is the `start-server` command: 9 10 alias mm='cd /home/dave/meow5 ; 11 tmux start-server \; source-file tmux.cmds' 12 13 (Newline and indenting just to make it fit in this log. 14 Also note the escaped semicolon: that's to separate the 15 two tmux commands (start-server and source-file) but not 16 have Bash interpret the semicolon as dividing two 17 separate shell commands! 18 19 I also have the barest begiinnings of a meow5.asm file. 20 The next tasks are: 21 22 1. Write the assembly to print "Meow" 23 2. Write the assembly to copy #1 five times in memory 24 and jmp to it so that we print "MeowMeowMeowMeowMeow" 25 26 A couple nights later, I'm halfway through that list: 27 28 ; A single meow 29 ; ----------------------------------------------- 30 mov ebx, STDOUT 31 mov ecx, meow ; str start addr 32 mov edx, (meow_end - meow) ; str length 33 mov eax, SYS_WRITE 34 int 0x80 35 end_print_meow: 36 mov ebx, 0 ; exit with happy 0 37 exit: ; (don't forget to set ebx to exit code) 38 mov eax, SYS_EXIT 39 int 0x80 40 41 Which works, of course: 42 43 $ ./build.sh run 44 Meow. 45 46 Okay, now how about just one simple copy. I'm also getting 47 more comfortable with writing simple NASM macros: 48 49 ; The First Test - Can I copy a meow? 50 ; ----------------------------------------------- 51 %define meow_len (end_print_meow - print_meow) 52 %define exit_len (end_exit - happy_exit) 53 54 ; copy meow printing code 55 mov edi, data_segment ; destination 56 mov esi, print_meow ; source 57 mov ecx, meow_len ; bytes to copy 58 rep movsb ; copy! 59 60 ; copy exit code 61 mov edi, (data_segment+meow_len) ; destination 62 mov esi, happy_exit ; source 63 mov ecx, exit_len ; len 64 rep movsb ; copy ecx bytes 65 66 ; jump to the copied code! 67 jmp data_segment 68 69 Crossing fingers and... 70 71 $ ./build.sh run 72 Meow. 73 Meow. 74 75 What!? That worked? Wow, first try! 76 77 I mean, OF COURSE it worked. Why wouldn't it? 78 79 Okay, so obviously I could copy "meow" five times in 80 this brute-force way. But the whole point is to do it 81 programatically as if I were really compiling several 82 words (functions) together into a larger word. 83 84 Couple nights later: disscovered the '$' preprocessor 85 symbol in NASM for the current address, so using that 86 for handier routine length calculations at the very 87 end of the routine: 88 89 print_meow: 90 ... 91 %assign meow_len ($ - print_meow) 92 93 Now I'm down to 1 meow, but that's okay. Progress 94 is slow and steady and my computing environment keeps 95 getting better. I've been reading nasmdoc.txt. 96 97 I've also been reviewing the basics and learning more 98 i386 assembly (basic 32-bit x86) from a great book 99 called 100 101 Programming from the Ground Up 102 by Jonathan Bartlett 103 104 Which, among other things, has helped me understand 105 _why_ you might want to choose one of the more 106 complicated i386 addressing modes. 107 108 Okay, next night. Baby steps and a lot of review (like, 109 I've gotten a little rusty with GDB too!). Here I'm 110 stepping through the simple copy-and-run program. 111 112 (Note that I edit the GDB sessions here for readability 113 and take out a fair amount of typos and redundant stuff 114 that I think would detract from understanding.) 115 116 I've already set register EDI to the first "destination" 117 address in my BSS segment where I'll inline ("compile") 118 my words (or "functions" or "routines"): 119 120 (gdb) display/x $edi 121 1: /x $edi = 0x804a00c 122 123 First we copy the meow word: 124 125 74 mov esi, print_meow ; source 126 75 mov ecx, meow_len ; bytes to copy 127 76 rep movsb ; copy! 128 1: /x $edi = 0x804a022 129 130 I was going to update my "here" pointer to the address 131 right after the copied meow, but I realized that EDI was 132 already there (and nothing was going to disturb it), so 133 why not just leave it alone and compile the exit word? 134 Here goes: 135 136 80 mov esi, happy_exit ; source 137 81 mov ecx, exit_len ; len 138 82 rep movsb ; copy ecx bytes 139 1: /x $edi = 0x804a02e 140 141 Looks good. So EDI now points at the next address after 142 the copied exit word. 143 144 (I probably shouldn't rely on EDI to always point to the 145 next destination address for inlined code, thoug. Other 146 so-called "string" instructions probably change it. So I 147 should probabbly use my "here" pointer like I'd 148 planned.) 149 150 Now if that was copied correctly, we can jump to it and 151 it'll print "Meow." as expected: 152 153 85 jmp data_segment 154 (gdb) s 155 0x0804a00c in data_segment () 156 (gdb) c 157 Continuing. 158 Meow. 159 [Inferior 1 (process 1391) exited normally] 160 161 Baby steps to doing this programatically. The next one 162 is creating an inline routine to do the copying: 163 164 ; inline function! 165 ; input: esi - word start source address 166 ; input: ecx - word length 167 inline: 168 mov edi, [here] ; destination 169 rep movsb 170 add edi, ecx ; update here pointer... 171 mov [here], edi ; ...and store it 172 ret 173 174 Now the "here" pointer to the data segment for my 175 "compiled" program is handled automatically. 176 177 Calling this is simple. Here's inlining a copy of Meow. 178 The exit one is identical except for the labels: 179 180 ; inline meow into the program: 181 mov esi, print_meow ; source 182 mov ecx, meow_len ; bytes to copy 183 call inline 184 185 It works: 186 187 Meow. 188 189 I think I'll inline five meows in a loop and call this 190 initial test a success: 191 192 ; inline five meows 193 mov eax, 5 ; 5 meows 194 inline_a_meow: 195 mov esi, print_meow ; source 196 mov ecx, meow_len ; bytes to copy 197 call inline 198 dec eax 199 jnz inline_a_meow 200 201 Feeling foolishly confident, I'm going to skip the 202 debugger and just build and run it this time: 203 204 dave@cygnus~/meow5$ mrun 205 Meow. 206 Meow. 207 Meow. 208 Meow. 209 Meow. 210 211 No way! I can still write a simple loop all on my own. I 212 guess this still really is sinking in and I really am 213 retaining it. Neat! 214 215 Well, this has hardly taken any time at all. The vast 216 majority of my evenings have been spent setting up this 217 laptop's environment to make it as easy as possible to 218 hop in and add a little bit each night. 219 220 The next task, which I'll start in log02.txt, will be to 221 store my words with some sort of header so they can be 222 looked up by name and so I don't have to manually create 223 and name the length calculations for every word in the 224 assembly source!