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~~ |