home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 1 / ARM_CLUB_CD.iso / contents / apps / program / k / mod_dis / Manual < prev    next >
Encoding:
Text File  |  1990-10-21  |  17.2 KB  |  380 lines

  1. >Manual
  2.  
  3. Directory Structure
  4. ===================
  5.  
  6.                                     MOD_DIS
  7.                                        |
  8.    +--------+----+-----+----+----------+-----------+-----------+---------+
  9.    |        |    |     |    |          |           |           |         |
  10. GetStarted  | Changes  | Checker    MODULES    ORIGINALS    SCRIPTS   SOURCES
  11.             |          |               |           |           |         |
  12.         Manual     ModDis201        ---+---     ---+---     ---+---   ---+---
  13.  
  14.  
  15.     GetStarted     Text    How to start quickly without reading the manual
  16.     Manual         Text    The manual
  17.     Changes        Text    Major changes since version 1.04
  18.     ModDis201      BASIC   The main program
  19.     Checker        BASIC   Checks the validity of a re-assembled module
  20.     MODULES        Dir     Newly-assembled modules are saved here
  21.     ORIGINALS      Dir     The module to be disassembled should be put here
  22.     SCRIPTS        Dir     User responses are stored here
  23.     SOURCES        Dir     Disassembled modules are stored here
  24.  
  25.  
  26. This is version 2.01 of ModDis, and replaces those versions previously
  27. published (0.E, 0.F and 1.04). It has various bug fixes and enhancements not
  28. available in previous versions. If you already have version 1.04, see the
  29. file Changes for details of important changes. If you don't want to read
  30. this manual yet try reading GetStarted and following its instructions.
  31.  
  32. ModDis a semi-intelligent module disassembler. It will read a relocatable
  33. module file from the ORIGINALS directory and attempt to disassemble it into
  34. a form suitable for the BASIC assembler. If successful, the output file is
  35. stored in the SOURCES directory, under the same filename as the module. If,
  36. as is likely, the program cannot resolve the disassembly unaided, it will
  37. prompt the user for help, hence the "semi-intelligent" description. These
  38. responses can be stored in the SCRIPTS directory and played back later to
  39. re-create the disassembly. The validity of the disassembly can be tested by
  40. re-assembling, which makes a new version in the MODULES directory. The BASIC
  41. program Checker can then be used to do a byte-by-byte comparison of the
  42. original and new versions.
  43.  
  44. I had already disassembled several modules by hand, and, while it is
  45. relatively easy, it becomes quite tedious as the module size increases. This
  46. program started as a quick utility to do some of the mechanical
  47. "donkey-work" aspects of disassembly, but has grown out of all proportion to
  48. its original aims. I have successfully disassembled about 30 of the RISC OS
  49. modules, and there are usually only a handful of errors to sort out in the
  50. output assembler listing (see the Problems section for details). You should
  51. be warned, however, that some of the larger RISC OS modules can produce
  52. thousands of lines of assembler listing.
  53.  
  54. There are more enhancements in the pipeline, but it will probably be some
  55. time before they become available.
  56.  
  57. In use
  58. ======
  59. Start by making ModDis your current directory, and load the ModDis201
  60. program. There is one feature which the user can change, located in
  61. PROCinit, around line 8000:
  62.           debug%=TRUE
  63. If debug% is TRUE, extra information is printed out in cyan while the
  64. program is running. I find it reassuring to be able to see what the program
  65. is doing. Setting it to FALSE will supress this printout, and there will be
  66. sometimes be long pauses when it is not obvious if the program is doing
  67. anything.
  68.  
  69. How the program works
  70. =====================
  71. The program identifies the "type" of each byte of the module, according to
  72. the following scheme:
  73.  
  74. type      description
  75. -4        'Acorn'-format compressed string
  76. -3        Padded string, ie a string padded with zeros up to a fixed length
  77. -2        Carriage-return-terminated string
  78. -1        Zero-terminated string
  79.  0        Don't know
  80.  1        A byte of data
  81.  2        A word (2 bytes of data)
  82.  3        Address, ie a 4-byte number pointing to another point in the module
  83.  4        A double word (4 bytes of data)
  84.  5        ARM code
  85.  6        Alignment bytes, 1, 2 or 3 bytes to bring us to a word boundary
  86.  7        External. See below
  87.  
  88. The first pass through the module is made armed with the entry points, eg
  89. initialisation code, finalisation code, etc. At this stage, ModDis is just
  90. setting the "type" of each byte it comes across, code, data or whatever. If
  91. it finds code, it follows it, and investigates branches and subroutine calls
  92. recursively, asking the user for help with identifying what it has found,
  93. where necessary. The program is smart enough to spot when the code ends, so
  94. it doesn't "fall off" into following data. It also recognises such things as
  95. SWI "OS_Exit", the zero-terminated string which always follows SWI
  96. "OS_WriteS",  and stuff like that.
  97.  
  98. After investigating all the entry points, it does one sequential pass
  99. through the module, searching for any bytes whose type has not yet been
  100. identified, and asking the user what they are.
  101.  
  102. Once all the types have been sorted out, the disassembly proper starts. If
  103. parts of the module are marked as data, they are expanded with EQU
  104. directives. The code is disassembled with calls to the Debugger module, but
  105. the following enhancements are made to its output:
  106.  
  107. 1. Labels are placed at all necessary points, as .xABCD where ABCD is the
  108.    offset in hex from the module start.
  109. 2. Wherever possible, sensible label names are constructed, eg SWI tables,
  110.    Keyword code, etc.
  111. 3. Branches are expanded to refer to labels.
  112. 4. Subroutines are identified by sABCD, rather than xABCD
  113. 5. PC-relative addressing is expanded as the ADR macro.
  114. 6. SWI names are enclosed in quotes.
  115. 7. The 2 instructions making up a 'long ADR' are recognised and represented
  116.    by a macro, FNadrl, to aid readability.
  117.  
  118.  
  119. The "What's this?" prompt
  120. =========================
  121. During the first pass through the module, the program will ask for help if
  122. it finds a reference to another part of the module, asking whether this
  123. reference is code to be disassembled, or data, in which case it wants to
  124. know what kind of data it is. The display looks like this:
  125.  
  126. [                 ]        This is the line currently being disassembled
  127. [    Block of     ]        and the three following, to show the context.
  128. [   yellow text   ]
  129. [                 ]
  130.                   
  131. [                 ]
  132. [    Block of     ]        A few lines preceding the reference
  133. [    white text   ]
  134. [                 ]
  135.  
  136. [     RED LINE    ]        The address being referred to
  137.  
  138. [                 ]
  139. [      More       ]        A few lines after the reference
  140. [    white text   ]
  141. [                 ]
  142.  
  143. What's this?               The prompt
  144.  
  145. The program expects a numeric response in the range -4 to 7.
  146.  
  147. It should be easy to tell if it's a string. Most strings are zero-terminated
  148. (type -1), but OS_CLI strings may be CR-terminated (-2). RISC OS menu labels
  149. are usually padded with zeros to 12 bytes; if you reply -3 you will be asked
  150. for the length of the padded string. 'Acorn'-format strings contain ASCII 27
  151. to indicate compressed dictionary entries; although zero-terminated they may
  152. also contain ASCII 0 immediately after ASCII 27.
  153.  
  154. Try to avoid replying 0 (don't know) if at all possible, because you'll have
  155. to answer sooner or later, and this may be your best oppertunity. There are
  156. however, two occasions when it is useful to answer 0. One is when the offset
  157. in question is obviously something like the module's title string, help
  158. string, or some other known entry point which is going to be recognised by
  159. the program later on. If you identify this offset now, it may not be fully
  160. followed-up by the program later. The other case is when the offset is
  161. pointing to the middle of an instruction, somewhere where a label cannnot be
  162. placed. See 'Odd labels' in the Problems section for more details.
  163.  
  164. Byte, word and address (1,2,3) are fairly rare. Make sure that the reference
  165. is word-aligned before replying 4 or 5 (double or code); getting this wrong
  166. will almost certainly cause an execution error later on. It is unlikely that
  167. a reference will be made to alignment bytes (6). See the External section
  168. below for details of type 7.
  169.  
  170. The "bytes of unknown type" prompt
  171. ==================================
  172. This prompt will occur during the final sequential pass through the module.
  173. The display looks like this:
  174.  
  175. [                 ]
  176. [    Block of     ]                A few lines preceding the address
  177. [    white text   ]
  178. [                 ]
  179.  
  180. [     RED LINE    ]                The address being referred to
  181.  
  182. [                 ]
  183. [      More       ]                A few lines after the address
  184. [    white text   ]
  185. [                 ]
  186.  
  187. n byte(s) at ABC of unknown type   The prompt
  188.  
  189. This is your last chance to work out unresolved byte types. Note that if
  190. n is 69, this means that there is a block of more than 68 bytes whose types
  191. are unknown. The allowed responses are the similar to those above, with the
  192. following changes:
  193.  
  194. You must NOT reply "don't know" (0) at this prompt. If you answer 1,2,3 or 4
  195. (byte, word, address, double) the program will ask you how many of these
  196. items there are. If you answer 5 (code), you may get some more "What's
  197. this?" type prompts as the program re-enters its recursive code-following
  198. phase, but it will eventually return to where it left off. Alignment bytes
  199. (6) are easily recognised as 1, 2 or 3 zeros at the end of a string,
  200. bringing it to a word boundary. See the External section below for details
  201. of type 7.
  202.  
  203. If you can see by inspection that the block of bytes contains more than one
  204. "type", simply reply with the type number of whatever comes first, and the
  205. program will re-prompt you for the remainder.
  206.                                             
  207.  
  208. The external type (7)
  209. =====================
  210. Rather than making the program general enough to cope with anything, I have
  211. allowed for the heading "none of the above" by creating type 7. If your
  212. module contains something weird, you can edit the program to cope with it,
  213. by writing your own PROCexternal, which marks the weird block as type 7,
  214. and PROCdisexternal, which copes with the disassembly of the block.
  215. For example, the RISC OS Desktop module contains 5 template files embedded
  216. in it (these appear under the DeskFS filing system). The PROCexternal
  217. supplied simply marks these 5 blocks as type 7 throughout, and
  218. PROCdisexternal loads the files in and increments the assembler counters
  219. O% and P% to jump over them. Something similar would be needed for the 6502
  220. emulator module, which contains embedded the BASIC ROM from the BBC.
  221.  
  222. Another good use for PROCexternal is if you know that the module contains a
  223. large block of, say, zero-terminated strings. rather than identifying each
  224. one individually at run time, you could put something like this in
  225. PROCexternal:
  226.  
  227.     FOR offset%=&1234 TO &2468
  228.       type%(offset%)=-1
  229.     NEXT
  230.  
  231. This will mark the block en-masse before the program proper starts.
  232.  
  233. CHECKER
  234. =======
  235. To verify that the disassembly worked, you can re-assemble the module; the
  236. new version is stored in directory MODULES. The program Checker does a
  237. byte-by-byte comparison of the original and new module, reporting on any
  238. differences it finds, as a disassembled instruction from each version. Any
  239. differences should be unimportant, as outlined in the Problems section below.
  240.  
  241.  
  242. PROBLEMS
  243. ========
  244. This is a list of known problem areas with ModDis. In most cases the
  245. problems are obscure, or difficult to correct in the program, but easy to
  246. spot and fix in the final assembler listing.
  247.  
  248. Immediate constants
  249. -------------------
  250. An immediate constant is expressed as an 8-bit value with a 4-bit rotation
  251. applied to it. This means that there can be more than one way of expressing
  252. a constant, eg #1 can be represented as #1 with 0 rotation, #4 with a
  253. rotation of 2, etc. The BASIC assembler hides this process from the
  254. programmer, who merely supplies the required constant and lets the assembler
  255. figure out how to represent it. If the original module has #1 stored as
  256. 4>>2, the disassembler will convert this to #1, and the BASIC assembler will
  257. reassemble it as 1>>0. This is functionally identical, but a byte-by-byte
  258. comparison of the two modules will show a difference.
  259.  
  260. Another related problem is that the program sometimes fails to expand the
  261. constant at all, giving something like MOV R0,#0,24, ie 0 rotated by 24,
  262. which is still 0. This format, which the program generates through the
  263. debugger module, is not valid for the BASIC assembler and should be replaced
  264. by MOV R0,#0. Some of these are detected and translated by the this version
  265. of the program, but it's not foolproof, and some still slip through. This
  266. problem is caused by a bug in the Debugger module. To solve it permanently,
  267. you need to modify the Debugger module itself, changing offset &920 from
  268. &1A000028  to &FA000028, effectively changing a BNE to a BNV. This seems to
  269. solve the problem, although I haven't tested this fix exhaustively, so
  270. proceed with caution.
  271.  
  272.  
  273. The ADR directive
  274. -----------------
  275. ADR Rn,#address is converted by the assembler into either SUB Rn,PC,#offset
  276. or ADD Rn,PC,#offset, depending on whether the address comes before or after
  277. the current PC value. A problem arises in that ADD Rn,PC,#0 is functionally
  278. identical to SUB Rn,PC,#0. The BASIC assembler always chooses the former, so
  279. if the latter occurs in a module it will be converted from SUB to ADD
  280. leading to an apparent difference between the modules when compared
  281. byte-by-byte. It should have no effect on running the module.
  282.  
  283.  
  284. Long labels
  285. -----------
  286. The assembler mnemonics start in column 20, leaving room for long labels.
  287. Sometimes, however, the labels are too long, in which case the mnemonic is
  288. moved to the next line, this being still syntactically correct. But if the
  289. label is exactly 19 characters long then it 'touches' the mnemonic, and BASIC
  290. sees this as one big label with a bad mnemonic after it. It's rare, so fix it
  291. manually if it happens.
  292.  
  293. The comment field
  294. -----------------
  295. The program generates a comment field which may be useful. If, however, it
  296. contains a colon, the BASIC assembler thinks this is a new statement
  297. starting. It's rare, so fix it manually. I also had a case once when the
  298. comment field contained the character &8D, which BASIC tried to tokenise. I
  299. did consider removing the commenr field altogether, as the simplest way of
  300. solving these problems, but overall it's too useful to lose, despite its
  301. problems.
  302.  
  303. SWI branch table
  304. ----------------
  305. The program attempts to match the SWI names to the SWI branch table, but it
  306. sometimes fails to identify the branch table as belonging to the SWI
  307. routine. In this case it substitutes labels of the type xABCD, so the
  308. assembly is still syntactically correct (and logically) correct. I think
  309. this is one of those things you're going to have to live with.
  310.  
  311. Embedded text
  312. -------------
  313. Something that cropped up in the NetPrint module was like this:
  314.           BL    s1234
  315.           EQUS  "A message"
  316.           More code...
  317. where the subroutine at s1234 adjusts the return address to skip the string.
  318. While ModDis recognises this if used with SWI "OS_WriteS", it cannot check
  319. for a user routine which does the same. ModDis will try to interpret the
  320. string as code, giving a warning message if this is not possible. It's up to
  321. you to be aware of this pitfall and watch out for it.
  322.  
  323. Floating point
  324. --------------
  325. Although ModDis could disassemble instructions intended for the FPU, in
  326. practice there isn't much point, since the BASIC assembler doesn't recognise
  327. them, so you could not re-assemble the module. Instead, it assumes that any
  328. FPU instruction it comes across is a mistake caused by an incorrect user
  329. response, and gives a warning message. I may do something about FPU at some
  330. time, but it's a low priority. In the meantime, if you want to disassemble a
  331. module which contains some FPU instructions, you will have to mark them as
  332. words (4-byte data).
  333.  
  334. Odd labels
  335. ----------
  336. Sometimes a reference is made to, for example, the byte BEFORE a block of
  337. data, the pointer being incremented before use. Something like:
  338.           ADR   xF6F
  339.           ........
  340.           MOV   PC,R14
  341. .xF70     EQUS  "...."
  342. It is not possible to place a label at &F6F, since it lies in the middle of
  343. an instruction. Instead, you should manually substitute something like this:
  344.           ADR   xF70-1
  345. This sort of thing is usually fairly easy to spot.
  346.  
  347. ALIGN
  348. -----
  349. When assembling a module, the ALIGN directive is used to move to a word
  350. boundary, simply incrementing the pointer by 1, 2 or 3. The bytes "skipped"
  351. like this are not explicitly set to zero, and will contain whatever was
  352. there at the time the module was originally compiled. When recompiling after
  353. running ModDis, these 'skipped" bytes may well have different values, and the
  354. Checker program will detect this, but since they play no part in the module,
  355. they are unimportant.
  356.  
  357.  
  358. THE END
  359. =======
  360.  
  361. My thanks to those users who reported bugs in the previous versions of
  362. ModDis, and to those who made suggestions on improving it. If you have any
  363. problems or (constructive) comments about ModDis, please get in touch with
  364. me. If you have any ideas for improving it, or if you extend it yourself,
  365. I'd be very glad to hear from you.
  366.  
  367. Lorcan Mongey
  368. 56 Salisbury Court
  369. Dublin Road
  370. Belfast BT7 1DD
  371. Tel: 0232 234386
  372.  
  373. I can also be reached at the following BBS:
  374.  
  375. BBS                    Telephone      Username         Number
  376. ---                    ---------      --------         ------
  377. CIX                    081 390 1244   lorcan@cix.uucp  
  378. The World of Cryton    0749 670030    lorcan           #237
  379. Arcade                 081 654 2212   lorcan           #417
  380.