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!