en:pfw:dump
Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| en:pfw:dump [2023-09-04 18:14] – gelöscht - Externe Bearbeitung (Unbekanntes Datum) 127.0.0.1 | en:pfw:dump [2023-09-05 06:33] (current) – ↷ Links angepasst, weil Seiten im Wiki verschoben wurden 157.90.7.32 | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| + | ===== DUMP memory algorithm: display content of main memory ===== | ||
| + | ==== DUMP idea ==== | ||
| + | |||
| + | A DUMP utility is a software tool that allows to inspect main memory and display it in a user readable form. | ||
| + | Typically output is composed of several lines that have the structure: | ||
| + | |||
| + | Display bytes starting in memory at a given address in hex (or other radix). Behind them is the ASCII representation of these bytes. | ||
| + | |||
| + | The DUMP utility is normally called '' | ||
| + | |||
| + | |||
| + | ==== DUMP Implementation ==== | ||
| + | |||
| + | One way to implement DUMP is to iterate in a loop line by line through memory. Say you want to display 16 bytes in each line, then this loop will start | ||
| + | at the start address and increment the address by 16 in each loop iteration. (If you want a different number of bytes in each line, adjust accordingly). | ||
| + | |||
| + | When you display memory in a single line you first output the current address and then have two loops that run one after the other iterating both from 0 to 15. | ||
| + | The first loop outputs bytes with two hexadecimal digits (or in decimal, or whatever you intend) and the second loop outputs the individual bytes as ASCII characters. | ||
| + | |||
| + | As some characters might control the output in a special way (so called control character such as 07 bell, 0A linefeed, 0C formfeed) it is wise to just output a period | ||
| + | instead of the actual character, in order to get a well formatted display. | ||
| + | |||
| + | |||
| + | ==== Pseudo code for the DUMP implementation ==== | ||
| + | |||
| + | < | ||
| + | Function: dump-line ( address -- ) | ||
| + | output address (possibly right aligned) | ||
| + | output ":" | ||
| + | | ||
| + | LOOP i from 0 to 15: | ||
| + | | ||
| + | | ||
| + | | ||
| + | LOOP i from 0 to 15: | ||
| + | | ||
| + | |||
| + | Function: dump ( address length -- ) | ||
| + | WHILE length is positive: | ||
| + | dump-line at address | ||
| + | increase address by 16 | ||
| + | decrease length by 16 | ||
| + | </ | ||
| + | |||
| + | ==== Minimal Forth implementation of DUMP: ==== | ||
| + | |||
| + | |||
| + | You can find a [[https:// | ||
| + | |||
| + | You can use it as follows: | ||
| + | |||
| + | <code forth> | ||
| + | ok | ||
| + | Create x 100 allot ok | ||
| + | x 100 dump | ||
| + | 03D694: 05 61 6C 6C 6F 74 08 00 DF 14 00 00 C1 00 08 00 | ||
| + | 03D6A4: 1F 18 00 00 C1 00 08 00 6F 10 00 00 C1 00 08 00 | ||
| + | 03D6B4: 4F 10 00 00 C2 00 08 00 1F 13 00 00 C2 00 08 00 | ||
| + | 03D6C4: 8F 30 00 00 C2 00 08 00 DF 14 00 00 C2 00 08 00 ? | ||
| + | 03D6D4: 1F 18 00 00 C2 00 08 00 6F 10 00 00 C2 00 08 00 | ||
| + | 03D6E4: 4F 10 00 00 C3 00 08 00 8F 30 00 00 C3 00 08 00 | ||
| + | 03D6F4: 5F 13 00 00 _... ok | ||
| + | </ | ||
| + | |||
| + | As the original Minimal Forth has no output facility other than '' | ||
| + | this implementation seems to be over complicated. | ||
| + | |||
| + | We extended Minimal Forth to [[https:// | ||
| + | more useful small Forth. | ||
| + | |||
| + | A DUMP utility in **GenericForth** can be found in [[en: | ||
| + | This example is factored using the pseudo code description. The character output has been factored into the useful word PEMIT ( char -- ) too. | ||
| + | |||
| + | |||
| + | ==== Various DUMP Implementations ==== | ||
| + | |||
| + | Other DUMP implementations can be found at the end of this description. | ||
| + | |||
| + | Your system might lack right justified number output or even BASE for printing numbers in other radix systems. The sample implementation in [[en: | ||
| + | |||
| + | |||
| + | ==== Background information ==== | ||
| + | |||
| + | More about the DUMP utility can found at the [[https:// | ||
| + | |||
| + | Some Forth DUMP implementations display a fixed amount of bytes and leave the updated address on the stack so that | ||
| + | you can invoke DUMP repeatedly to display successive regions of memory. | ||
| + | |||
| + | ==== Possible pitfalls with DUMP ==== | ||
| + | |||
| + | Some systems have hardware memory protection that is triggered if you access memory outside the reserved area. | ||
| + | The dump utility can do so by trying to show this forbidden memory. Triggered memory protect might stop the current process and | ||
| + | terminate your session. If necessary a suitable test for the validity of used addresses might be reasonable on such systems so that | ||
| + | dump can issue a normal error message (or display dummy data) in theses cases and leave the system / session otherwise intact. | ||
| + | |||
| + | ==== Contributions ==== | ||
| + | |||
| + | < | ||
| + | |||
| + | ====== GForth 0.7.3 ====== | ||
| + | |||
| + | |||
| + | Please note: The below code uses recognisers for numbers and non Generic Forth words: <= BLANK (BL FILL) | ||
| + | |||
| + | < | ||
| + | \ Adapted from Z79Forth. Validated against GNU Forth 0.7.3. | ||
| + | |||
| + | : .doubles ( -- ) $10 0 DO | ||
| + | [CHAR] 0 EMIT I 1 .R SPACE | ||
| + | LOOP ; | ||
| + | : .singles ( -- ) $10 0 DO | ||
| + | I 1 .R | ||
| + | LOOP ; | ||
| + | : .header ( -- ) 1 CELLS 2* 1+ SPACES .DOUBLES .SINGLES CR ; | ||
| + | |||
| + | : .addr S>D <# 1 CELLS 2* 0 DO # LOOP #> TYPE SPACE ; | ||
| + | : .data S>D <# # # #> TYPE SPACE ; | ||
| + | : tochar DUP BL $7F WITHIN 0= IF DROP [CHAR] . THEN ; | ||
| + | |||
| + | VARIABLE start \ Base addr. of the interesting area | ||
| + | VARIABLE bytecount | ||
| + | CREATE asciib 16 ALLOT \ Buffer for the ASCII character dump | ||
| + | |||
| + | : dump.initvars.prtheader ( baseaddr bytecount -- align16 ) | ||
| + | bytecount ! DUP start ! $-10 AND | ||
| + | ( baseaddr bytecount ) HEX CR .header ; | ||
| + | |||
| + | : asciidump asciib $10 TYPE ; | ||
| + | |||
| + | : dump.sanitycheck ( baseaddr bytecount -- baseaddr bytecount ) | ||
| + | DEPTH 2 < IF ABORT THEN | ||
| + | DUP 0 <= IF ABORT THEN ; | ||
| + | |||
| + | : dump.iskip.bcount ( addr -- skipbytecount ) | ||
| + | start @ $-10 AND = IF | ||
| + | start @ $F AND EXIT | ||
| + | THEN 0 ; | ||
| + | |||
| + | : dump ( baseaddr bypecount -- ) dump.sanitycheck | ||
| + | BASE @ >R | ||
| + | dump.initvars.prtheader >R | ||
| + | BEGIN \ R: saved_BASE currentdumpaddr | ||
| + | I $F AND 0= IF \ Beginning of a dump line | ||
| + | I .addr \ Print the base block address | ||
| + | asciib $10 BLANK \ Initialize the ASCI dump area | ||
| + | THEN | ||
| + | |||
| + | I dump.iskip.bcount ?DUP IF | ||
| + | \ Interesting data not reached yet | ||
| + | DUP 3 * SPACES | ||
| + | R> + >R \ Skip the uninteresting part | ||
| + | THEN | ||
| + | |||
| + | I C@ DUP .data | ||
| + | tochar I $F AND asciib + C! | ||
| + | bytecount DUP @ 1- OVER ! \ bytecount | ||
| + | |||
| + | @ 0= IF \ Last dump line | ||
| + | $F I $F AND - 3 * SPACES | ||
| + | asciidump SPACE | ||
| + | R> DROP R> BASE ! | ||
| + | EXIT \ We are done here. | ||
| + | THEN | ||
| + | |||
| + | R> 1+ >R | ||
| + | I $F AND 0= IF \ Last column of non-last line | ||
| + | asciidump CR | ||
| + | THEN | ||
| + | AGAIN ; | ||
| + | |||
| + | </ | ||
| + | |||
| + | [[en: | ||
| + | |||
| + | ~~DISCUSSION~~ | ||