📄 mdk_gstart.texi
字号:
@exampleguile> (define my-run (lambda (file) (mix-load file) (let ((start (mix-loc))) (mix-run) (mix-pmem start (mix-loc)))))guile> (my-run "hello")Program loaded. Start address: 3000Running ...MIXAL HELLO WORLD ... doneElapsed time: 11 /Total program time: 11 (Total uptime: 11)3000: + 46 58 00 19 37 (0786957541)3001: + 00 00 00 02 05 (0000000133)3002: + 14 09 27 01 13 (0237350989)guile> @end exampleAs you can see, the possibilities are virtually unlimited. Of course,you don't need to type a function definition each time you start@code{mixguile}. You can write it in a file, and load it using Scheme's@code{load} function. For instance, you can create a file named, say,@file{functions.scm} with your definitions (or any Scheme expression)and load it at the @code{mixguile} prompt:@exampleguile> (load "functions.scm")@end exampleAlternatively, you can make @code{mixguile} to load it for you. When@code{mixguile} starts, it looks for a file named @file{mixguile.scm} inyour MDK configuration directory (@file{~/.mdk}) and, if it exists,loads it before entering the REPL. Therefore, you can copy yourdefinitions in that file, or load the @file{functions.scm} file in@file{mixguile.scm}.@node Hook functions, Scheme scripts, Defining new functions, Using mixguile@subsection Hook functions@cindex hook function@cindex pre-hook@cindex post-hookHooks are functions called before or after a given event occurs. In@code{mixguile}, you can define command and break hooks, which areassociated, respectively, with command execution and programinterruption events. The following sections give you a tutorial on usinghook functions within @code{mixguile}.@menu* Command hooks:: * Break hooks:: @end menu@node Command hooks, Break hooks, Hook functions, Hook functions@subsubsection Command hooksIn the previous section, we have seen how to extend @code{mixguile}'sfunctionality through the use of user defined functions. Frequently,you'll write new functions that improve in some way the workings of abuilt-in @code{mixvm} command, following this pattern:@enumerate a@itemPrepare the command execution@itemExecute the desired command@itemPerform post execution operations@end enumerateWe call the functions executed in step (a) @dfn{pre-hook}s, and those ofstep @dfn{post-hook}s of the given command. @code{mixguile} lets youspecify pre- and post-hooks for any @code{mixvm} command using the@code{mix-add-pre-hook} and @code{mix-add-post-hook} functions, whichtake as arguments a symbol naming the command and a function to beexecuted before (resp. after) the command. In other words,@code{mixguile} will execute for you steps (a) and (c) above wheneveryou eval (b). The hook functions must take a single argument, which is astring list of the command's arguments. As an example, let us define thefollowing hooks for the @code{next} command:@example(define next-pre-hook (lambda (arglist) (mix-slog #f)))(define next-post-hook (lambda (arglist) (display "Stopped at line ") (display (mix-src-line-no)) (display ": ") (display (mix-src-line)) (newline) (mix-slog #t)))@end example@noindentIn these functions, we are using the function @code{mix-slog} to turnoff the informational messages produced by the virtual machine, since weare providing our own ones in the post hook function. To install thesehooks, we would write:@example(mix-add-pre-hook 'next next-pre-hook)(mix-add-post-hook 'next next-post-hook)@end example@noindentAssuming we have put the above expressions in @code{mixguile}'sinitialisation file, we would obtain the following results whenevaluating @code{mix-next}: @exampleguile> (mix-next)MIXAL HELLO WORLD Stopped at line 6: HLT guile> @end exampleAs a second, more elaborated, example, let's define hooks which printthe address and contents of a cell being modified using @code{smem}. Thehook functions could be something like this:@example(define smem-pre-hook (lambda (arglist) (if (eq? (length arglist) 2) (begin (display "Changing address ") (display (car arglist)) (newline) (display "Old contents: ") (display (mix-cell (string->number (car arglist)))) (newline)) (error "Wrong arguments" arglist))))(define smem-post-hook (lambda (arglist) (if (eq? (length arglist) 2) (begin (display "New contents: ") (display (mix-cell (string->number (car arglist)))) (newline)))))@end example@noindentand we can install them using@example(mix-add-pre-hook 'smem smem-pre-hook)(mix-add-post-hook 'smem smem-post-hook)@end example@noindentAferwards, a sample execution of @code{mix-smem} would look like this:@exampleguile> (mix-smem 2000 100)Changing address 2000Old contents: 0New contents: 100guile>@end example@cindex global hookYou can add any number of hooks to a given command. They will beexecuted in the same order as they are registered. You can also defineglobal post (pre) hooks, which will be called before (after) any@code{mixvm} command is executed. Global hook functions must admit twoarguments, namely, a string naming the invoked command and a string listof its arguments, and they are installed using the Scheme functions@code{mix-add-global-pre-hook} and @code{mix-add-global-post-hook}. Asimple example of global hook would be:@exampleguile> (define pre-hook (lambda (cmd args) (display cmd) (display " invoked with arguments ") (display args) (newline)))guile> (mix-add-global-pre-hook pre-hook)okguile> (mix-pmem 120 125)pmem invoked with arguments (120-125)0120: + 00 00 00 00 00 (0000000000)0121: + 00 00 00 00 00 (0000000000)0122: + 00 00 00 00 00 (0000000000)0123: + 00 00 00 00 00 (0000000000)0124: + 00 00 00 00 00 (0000000000)0125: + 00 00 00 00 00 (0000000000)guile>@end exampleNote that if you invoke @code{mixvm} commands within a global hook, itsassociated command hooks will be run. Thus, if you have installed boththe @code{next} hooks described earlier and the global hook above,executing @code{mix-next} will yield the following result:@exampleguile> (mix-next 5)next invoked with arguments (5)slog invoked with arguments (off)MIXAL HELLO WORLD Stopped at line 7: MSG ALF "MIXAL"slog invoked with arguments (on)guile> @end exampleAdventurous readers may see the above global hook as the beginning of acommand log utility or a macro recorder that saves your commands forreplay.@node Break hooks, , Command hooks, Hook functions@subsubsection Break hooks@cindex break hookWe have seen in the previous section how to associate hooks to commandexecution, but they are not the whole story. You can also associate hookfunctions to program interruption, that is, specify functions thatshould be called every time the execution of a MIX program is stoppeddue to the presence of a breakpoint, either explicit orconditional. Break hooks take as arguments the line number and memoryaddress at which the break occurred. A simple hook that logs the lineand address of the breakpoint could be defined as:@example(define break-hook (lambda (line address) (display "Breakpoint encountered at line ") (display line) (display " and address ") (display address) (newline)))@end example@noindentand installed for explicit and conditional breakpoints using@example(mix-add-break-hook break-hook)(mix-add-cond-break-hook break-hook)@end example@noindentafter that, every time the virtual machine encounters a breakpoint,@code{break-code} shall be evaluated for you@footnote{You may havenoticed that break hooks can be implemented in terms of command hooksassociated to @code{mix-run} and @code{mix-next}. As a matter of fact,they @emph{are} implemented this way: take a look at the file@file{@emph{install_dir}/share/mdk/mix-vm-stat.scm} if you are curious.}.@node Scheme scripts, , Hook functions, Using mixguile@subsection Scheme scripts@cindex Scheme script@cindex non-interactiveAnother useful way of using @code{mixguile} is writing executablescripts that perform a set of commands for you. This is done using the@code{mixguile} switch @code{-s} (being a Guile shell, @code{mixguile}accepts all the command options of @code{guile}; type @code{mixguile -h}for a list of all available command options). For instance, if you havea very useful MIX program @file{foo.mix} which you want to run often,you don't have to fire a MIX virtual machine, load and run it everytime; you can write a Scheme script instead:@example#! /usr/bin/mixguile -s!#;;; runprimes: execute the primes.mix program;; load the file you want to run(mix-load "../samples/primes");; execute it(mix-run);; print the contents of registers(mix-pall);; ...@end exampleJust save the above script to a file named, say, @file{runtest}, make itexecutable (@code{chmod +x runtest}), and, well, execute it from theUnix shell:@example$ ./runtestProgram loaded. Start address: 3000Running ...... doneElapsed time: 190908 /Total program time: 190908 (Total uptime: 190908)rA: + 30 30 30 30 30 (0511305630)rX: + 30 30 32 32 39 (0511313959)rJ: + 47 18 (3026)rI1: + 00 00 (0000) rI2: + 55 51 (3571) rI3: + 00 19 (0019) rI4: + 31 51 (2035) rI5: + 00 00 (0000) rI6: + 00 00 (0000) Overflow: FCmp: L$@end exampleNote that this is far more flexible that running programsnon-interactively using @code{mixvm} (@pxref{Non-interactive mode}), foryou can execute any combination of commands you want from a Schemescript (not just running and dumping the registers). For additional@code{mixguile} command line options, see @ref{Invoking mixguile}.@node Using Scheme in mixvm and gmixvm, , Using mixguile, Getting started@section Using Scheme in @code{mixvm} and @code{gmixvm}@cindex @code{scmf}In the previous section (@pxref{Using mixguile}) we have seen how theGuile shell @code{mixguile} offers you the possibility of using Schemeto manipulate a MIx virtual machine and extend the set of commandsoffered by @code{mixvm} and @code{gmixvm}. This possibility is notlimited to the @code{mixguile} shell. Actually, both @code{mixvm} and@code{gmixvm} incorporate an embedded Guile interpreter, and canevaluate Scheme expressions. To evaluate a single-line expression at the@code{mixvm} or @code{gmixvm} command prompt, simply write it and pressreturn (the command parser will recognise it as a Scheme expressionbecause it is parenthesized, and will pass it to the Guileinterpreter). A sample @code{mixvm} session using Scheme expressionscould be:@exampleMIX > load helloProgram loaded. Start address: 3000MIX > (define a (mix-loc))MIX > runRunning ...MIXAL HELLO WORLD ... doneElapsed time: 11 /Total program time: 11 (Total uptime: 11)MIX > (mix-pmem a)3000: + 46 58 00 19 37 (0786957541)MIX > (mix-pmem (mix-loc))3002: + 14 09 27 01 13 (0237350989)MIX >@end exampleYou can also load and evaluate a file, using the @code{scmf}command like this:@exampleMIX> scmf /path/to/file/file.scm@end exampleTherefore, you have at your disposal all the @code{mixguile} goodiesdescribed above (new functions, new command definitions, hooks...)inside @code{mixvm} and @code{gmixvm}. In other words, these programsare extensible using Scheme. See @ref{Using mixguile} for examples ofhow to do it.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -