akkartik / mu

Soul of a tiny new machine. More thorough tests → More comprehensible and rewrite-friendly software → More resilient society.
http://akkartik.name/akkartik-convivial-20200607.pdf
Other
1.35k stars 47 forks source link

exercise: reimplement writing a string to a stream #22

Closed akkartik closed 5 years ago

akkartik commented 5 years ago

To see the failing tests:

$ ./subx translate 05[0-7]*.subx -o a.elf  &&  ./subx run a.elf test

Feel free to push changes to this branch as you like.

This exercise should get you thinking about arrays and streams of bytes, a couple of foundational data structures for us. It should also focus attention on the couple of instructions in subx help opcodes that operate on r8/m8 values.

The write function is pretty foundational, so many tests now fail in the project as a whole. The above command focuses on the immediately failing tests. If these pass then everything else should, as well.

When (when!) you need to debug things, go back and reread https://github.com/akkartik/mu/blob/master/subx/Readme.md#a-few-hints-for-debugging. And, of course, feel free to email me.

charles-l commented 5 years ago

OK, definitely a good intro to streams/strings structures. Besides burning 3 hours trying to track down a silly bug because I mistakingly thought I'd written a 12-byte offset but it was in base-16 (should have been 0xc, not 12) it was pretty straightforward.

akkartik commented 5 years ago

Excellent work! How did you track down the bug?

charles-l commented 5 years ago

I labeled each line of assembly, and checked the output in the trace to ensure it was doing what I expected.

e.g.

$get-f:
    8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .                         2/r32/EDX   8/disp8         .                 # copy *(EBP+8) to EDX
$get-f->length:
    8b/copy                         1/mod/*+disp8   2/rm32/EDX    .           .                         1/r32/ECX   8/disp8         .                 # copy *(EDX+8) to ECX
$get-f->data[f->length]:
    8d/copy-address                 1/mod/*+disp8   4/rm32/sib    2/base/EDX  1/index/ECX   .           1/r32/ECX   0xc/disp8        .                 # copy EDX+ECX+12 to ECX
$push-f->data[f->length]:
    51/push-ECX

The trace basically had all the info I needed, I just didn't see it the first few times around.

If the trace dumped the comments above the current instruction that'd add the extra metadata to the trace that I needed to identify which instructions were the ones I cared about (perhaps tracing comments with the prefix of DEBUG, or adding a pseudo instruction could help with this?).

BTW, test_apps is failing now, and I'm not entirely clear on why the handle test is diffing the binaries...

Is this implementation making the bootstrap step fail?

https://travis-ci.org/akkartik/mu/jobs/525453428

akkartik commented 5 years ago

Yeah, I saw the CI failure. Since I'm bundling binaries for the examples it seems useful to ensure they're in sync. Basically I have reproducible builds for some very small examples.

The way to keep test_apps happy is to run test_apps record when changing .subx files. But for a PR that won't be merged you don't need to bother.

akkartik commented 5 years ago

You're right that I've often wished I could print out the current instruction in its entirety. So far it's seemed to take a lot of (duplicate) code, but maybe I should just bite the bullet.

One compromise is support for tracing the name of function labels in call instructions. You'll encounter that soon.

Unfortunately comments don't make it to the ELF binary. So I'm not sure how I'd add them.

akkartik commented 5 years ago

Maybe I should create a map file from address to entire source line. Hmm, that shouldn't be much work..

akkartik commented 5 years ago

The trace now shows source lines where possible! Try it out. Do a git pull and then:

./subx --debug translate 05[0-7]*.subx -o a.elf
./subx --debug --trace run a.elf test
../browse_trace/browse_trace last_run

(I renamed the --map command-line flag to --debug since it now saves debug info in multiple files. I also changed the trace format a bit.)

The commit: https://github.com/akkartik/mu/commit/02684e8d7cb5292867ebcdea06879b94ba63aef4