⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 basbits.html

📁 关于ARM汇编的非常好的教程
💻 HTML
📖 第 1 页 / 共 2 页
字号:
<!doctype html public "-//W3C//DTD HTML 3.2//EN"><html><head><title>Special facilities from BASIC</title><meta http-equiv="content-type" content="text/html; charset=ISO-8859-1" /><meta http-equiv="content-language" content="en" /><meta name="resource-type" content="document"><meta name="copyright" content="This document copyright 2001 by Richard Murray. Use for non-profit and education purposes explicitly granted."><meta name="author" content="Richard Murray"><meta name="rating" content="general"></head><!--  /assembler/basbits.html            --><!--                                     --><!--  (C) Copyright 2001 Richard Murray  --><!--  Designed by Richard Murray         --><!--  rmurray@heyrick.co.uk              --><!--                                     --><body bgcolor="#f0f0f0" text="#000000" link="#0022dd" vlink="#002288"><table border = "0" width="100%">  <tr>    <td align=center width=100>      <img src="arm3.gif" width=79 height=78 align = middle>    </td>    <td>      <h1 align="center"><font color="#800080">Special facilities<br>available from BASIC</font></h1>    </td>    <td align=center width=100>      <img src="arm3.gif" width=79 height=78 align = middle>    </td></table><p>&nbsp;<p>We all know that BASIC uses...<ul>  <li> <b>A%</b> to <b>H%</b> for registers R0 to R7  <li> <b>L%</b> for code limit check (if required)  <li> <b>O%</b> for offset assembly (if required)  <li> <b>P%</b> for Program Counter</ul>But there is more. Much more, some of which I didn't know existed for nearly a decade (such arethe disadvantages of self-taught programming!).<p>When you CALL or USR an assembly language segment, BASIC sets the registers as follows:<table>  <tr> <td width=50>R0  <td>A%  <tr> <td>R1  <td>B%  <tr> <td>R2  <td>C%  <tr> <td>R3  <td>D%  <tr> <td>R4  <td>E%  <tr> <td>R5  <td>F%  <tr> <td>R6  <td>G%  <tr> <td>R7  <td>H%  <tr> <td>R8  <td>Pointer to BASIC's workspace (ARGP)  <tr> <td>R9  <td>Pointer to list of l-values for the parameters  <tr> <td>R10 <td>Number of parameters  <tr> <td>R11 <td>Pointer to BASIC's string accumulator (STRACC)  <tr> <td>R12 <td>BASIC's LINE pointer (points to current statement)  <tr> <td>R13 <td>Pointer to BASIC's stack (full, descending - as RISC OS uses)  <tr> <td>R14 <td>Return address, and environment information pointer</table>Of those, two hide a lot of detail...<p>&nbsp;<p>&nbsp;<p><h2>R9 (and R10)</h2>R9 points to a list that provides information of each variable passed as a parameter to CALL.<br>This is, for example:<br><code>&nbsp;&nbsp;CALL mycode, pointer%, string$, real</code><br>and is different to just setting A%-H%.<br>Parameters to CALL are not often used, as they are not as easy to implement as settingregisters.<p>For each variable given, two words (word aligned) are used. The first is known as the l-value. InEnglish, this is the address where the value of this variable is stored. The second word is adescriptor.<br>The list is in reverse order, the last variable passed to CALL is the first given in the list. Inthis way, R9 always points to the last entry in the list. The pointer is always valid, even whenthe variables counter (R10) is zero.<p>The possible variable types are:<table border = 1>  <!-- The &nbsp; codes are to force the cell width, to look tidier, without having to resort       to absolute pixel widths, which are worse than useless. Why they never implemented       percentage widths for cells (they did it for tables!) is beyond me... -->  <tr> <td><b>Type</b> <td><b>BASIC</b> <td><b>l-value points to</b> <td><b>in English...</b>  <tr> <td valign=top>&amp;00 <td>?factor <td>byte-aligned byte <td>Pointer to actual byte  <tr> <td valign=top>&amp;04 <td>!factor<br>integer%<br>integer%(n)  <td>byte-aligned word<br>word-aligned word<br>word-aligned word <td>Pointer to four-byte integer<br>(may not be word-aligned)  <tr> <td valign=top>&amp;05 <td rowspan=2>|factor<br>real<br>real(n) <td>byte-aligned&nbsp;FP&nbsp;value&nbsp;(5&nbsp;bytes) <td>Pointer to five-byte floating point value  <tr> <td valign=top>&amp;08 <td>word-aligned&nbsp;FP&nbsp;value&nbsp;(8&nbsp;bytes) <td>Pointer to 8-byte floating point value<br>(BASIC VI)  <tr> <td valign=top>&amp;80 <td>string$<br>string$(n) <td>byte-aligned SIB (5 bytes) <td>Pointer to string information block  <tr> <td valign=top>&amp;81 <td>$factor <td>byte-aligned byte-string (CR terminated) <td>Pointer to string  <tr> <td valign=top>&amp;100 + &amp;04 <td>integer%() <td rowspan=3>word-aligned&nbsp;array&nbsp;pointer <td rowspan=3>Pointer to word-aligned word. If array unallocated, or LOCAL but not yet DIMed, this word is less than 16. Otherwise, this word points to the array structure.  <tr> <td valign=top>&amp;100 + &amp;05<br>&amp;100 + &amp;08 <td>real()  <tr> <td valign=top>&amp;100&nbsp;+&nbsp;&amp;80 <td>string$()</table><p>The String Information Block is comprised of four bytes comprising the address of the string,followed by a byte giving the length of the string.<p>The word array structure (for types &amp;100 + &lt;something&gt;) is a word aligned list ofinteger subscript sizes (the values in the DIM, plus one) terminated by a zero word, followed by a word which contains the total number of elements in the array, followed by the entries in the array.<p>Here is an example of passing a string to CALL, and printing it in assembler. Notice how we needto use LDRB to load the string pointer, as the address is byte aligned.<pre><font size = -1>REM &gt;stringprntREMREM String passing (via CALL) demonstrationREMREM By Richard MurrayREM Downloaded from http://www.heyrick.co.uk/assembler/REMcodesize% = 180 : REM The code is 180 bytesDIM code% codesize%PROCbuild_codeINPUT &quot;Please enter some text: &quot;my_string$PRINT '&quot;Entering assembler...&quot;CALL print_string, my_string$PRINT &quot;...returned from assembler&quot;'END:DEFPROCbuild_code  FOR loop% = 8 TO 10 STEP 2    P% = code%    L% = code% + codesize%    [ OPT    loop%      \ Note... This is coded for CLARITY, not speed!    .print_string      CMP    R10, #1              ; Check one parameter was given      BNE    wrong_parameters      LDR    R0, [R9]             ; Load pointer      LDR    R1, [R9, #4]         ; Load type      CMP    R1, #&amp;80             ; Is it a string?      BNE    wrong_var_type      \ Word giving string pointer may not be word aligned, so we      \ cannot use an LDR as results for non-aligned addresses      \ are unpredictable...      LDRB   R1, [R0], #1      LDRB   R2, [R0], #1      ADD    R1, R1, R2, LSL#8      LDRB   R2, [R0], #1      ADD    R1, R1, R2, LSL#16      LDRB   R2, [R0], #1      ADD    R1, R1, R2, LSL#24      LDRB   R2, [R0], #4         ; Length      CMP    R2, #0               ; Check length      BEQ    exit      \ Now, R1 is string pointer and R2 is string length.    .loop      LDRB   R0, [R1], #1      SWI    &quot;OS_WriteC&quot;      SUBS   R2, R2, #1           ; SUBS sets Z bit when = 0      BNE    loop    .exit      SWI    &quot;OS_NewLine&quot;         ; So a blank string prints just that...      MOV    PC, R14    .wrong_parameters      SWI    &quot;OS_WriteS&quot;      EQUS   &quot;Incorrect number of parameters&quot;+CHR$0      ALIGN      B      passed_to_call    .wrong_var_type      SWI    &quot;OS_WriteS&quot;      EQUS   &quot;Wrong variable type&quot;+CHR$0      ALIGN      ; B      passed_to_call      ; Not required, will fall through    .passed_to_call      \ rudimentary optimisation! &lt;g&gt;      SWI    &quot;OS_WriteS&quot;      EQUS   &quot; passed to call&quot;+CHR$13+CHR$10+CHR$0      ALIGN      MOV    PC, R14    ]  NEXTENDPROC</font></pre><div align = right><a href="sw/stringprnt.basic"><i>Download this example</i></a></div><p>&nbsp;<p>&nbsp;<p><h2>R14</h2>Traditionally, <code>R14</code> is the Link Register to return from yourcode to BASIC.<p>Following that are a list of words which are offsets from the ARGP (in R8).<br>For example, you might want to know the current value of PAGE without tying up a register topass that value your code. PAGE is available at offset &amp;08, so your code would be somethinglike:<br><code>&nbsp;&nbsp;LDR R0, [R14, #8]<br>&nbsp;&nbsp;LDR R0, [R8, R0]</code><p><table border = 1>  <tr> <td valign=top><b>Offset</b> <td><b>Name</b> <td><b>Meaning</b>  <tr> <td valign=top>&amp;00 <td>RETURN <td>Return address to BASIC  <tr> <td valign=top>&amp;04 <td>STRACC <td>String accumulator (256 bytes long)  <tr> <td valign=top>&amp;08 <td>PAGE <td>The current value of PAGE  <tr> <td valign=top>&amp;0C <td>TOP <td>The current value of TOP  <tr> <td valign=top>&amp;10 <td>LOMEM <td>The current start of variable storage  <tr> <td valign=top>&amp;14 <td>HIMEM <td>The current stack end  <tr> <td valign=top>&amp;18 <td>MEMLIMIT <td>Limit of available memory  <tr> <td valign=top>&amp;1C <td>FSA <td>Free space start (end of variables/stack limit)  <tr> <td valign=top>&amp;20 <td>TALLY <td>Value of COUNT  <tr> <td valign=top>&amp;24 <td valign=top>TRACEF <td>TRACE FILE handle, or 0 if no file being TRACEd to<br>Four words follow the trace file handle, that may be of use to you:<br><code>+&nbsp;4&nbsp; LOCALARLIST - </code>a pointer to the list of local arrays<br><code>+&nbsp;8&nbsp; INSTALLLIST - </code>a pointer to the list of installed libraries<br><code>+12&nbsp; LIBRARYLIST - </code>a pointer to the list of transient libraries<br><code>+16&nbsp; OVERPTR&nbsp;&nbsp;&nbsp;&nbsp; - </code>a pointer to the overlay structure<br>&nbsp;<br>Libraries are stored as a word which is the pointer to the next library, or 0 to end. This wordis followed by the BASIC program which is the library.<br>&nbsp;<br>Before OVERLAY has been executed, OVERPTR is zero. Afterwards, OVERPTR contains a pointer to thefollowing structure:<br><code>OVERPTR+&amp;00 </code>Pointer to base of OVERLAY array (such as 'lib$(0)')<br><code>OVERPTR+&amp;04 </code>Index of current OVERLAY file (or -1 if none loaded)<br><code>OVERPTR+&amp;08 </code>Total allowed size of OVERLAY area<br><code>OVERPTR+&amp;0C </code>Start of current OVERLAY file in memory  <tr> <td valign=top>&amp;28 <td>ESCWORD <td>Exception flag word (contains escflg, trcflg)  <tr> <td valign=top>&amp;2C <td>WIDTHLOC <td>The value of WIDTH - 1  <tr> <td colspan = 3>&nbsp;<br>Then come branches to internal BASIC routines...<br>&nbsp;<br>  <tr> <td valign=top>&amp;30 <td valign=top>VARIND <td>Get value of l-value<br>&nbsp;<br>On entry:<br><code>&nbsp;R0&nbsp; </code>= Address to load variable from<br><code>&nbsp;R9&nbsp; </code>= Type of variable (as in CALL parameter block)<br><code>&nbsp;R12 </code>= LINE<br>&nbsp;<br>Returns with R0 - R3 as the value (or F0 in BASIC VI), R9 the type.<br><code>R9 = &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0 </code>- String; STRACC is start, R2 is end, [R2]-STRACC is the length<br><code>R9 = &amp;40000000 </code>- Interger; in R0<br><code>R9 = &amp;80000000 </code>- Float; in R0...R3<br>Registers preserved.  <tr> <td valign=top>&amp;34 <td valign=top>STOREA <td>Store a variable, optionally converting between formats<br>&nbsp;<br>On entry:<br><code>&nbsp;R0...R3 </code>= Value (or F0 if float in BASIC VI)<br><code>&nbsp;R4&nbsp; </code>= Address to store at<br><code>&nbsp;R5&nbsp; </code>= Type of variable (as in CALL parameter block)<br><code>&nbsp;R8&nbsp; </code>= ARGP<br><code>&nbsp;R9&nbsp; </code>= Type of value<br><code>&nbsp;R12 </code>= LINE<br><code>&nbsp;R13 </code>= Stack pointer<br>&nbsp;<br>Returns with R0 - R7 corrupted.  <tr> <td valign=top>&amp;38 <td valign=top>STSTORE <td>Store a string into a string variable<br>&nbsp;<br>On entry:<br><code>&nbsp;R2&nbsp; </code>= Length (address of byte beyond the last one)<br><code>&nbsp;R3&nbsp; </code>= Address of start of string<br><code>&nbsp;R4&nbsp; </code>= Address of l-value (ie, where to store it)<br><code>&nbsp;R8&nbsp; </code>= ARGP<br><code>&nbsp;R9&nbsp; </code>= Type of value<br><code>&nbsp;R12 </code>= LINE<br><code>&nbsp;R13 </code>= Stack pointer<br>&nbsp;<br>Corrupts R0, R1, R5, R6 and R7.<br>String must start on a word boundary, and length must be 255 or less.  <tr> <td valign=top>&amp;3C <td valign=top>LVBLNK <td>Looks up a variable by name<br>&nbsp;<br>On entry:<br><code>&nbsp;R8&nbsp; </code>= ARGP<br><code>&nbsp;R11 </code>= Pointer to start of name<br><code>&nbsp;R12 </code>= LINE<br><code>&nbsp;R13 </code>= Stack pointer<br>&nbsp;<br>May use the stack. Uses all registers.<br>&nbsp;<br>If variable (more precisely, l-value) was found, returns with:<br>Z flag = 0, R0 = address of l-value, and R9 = Type of l-value<br>&nbsp;<br>If not found, returns with:<br>Z flag = 1<br>C flag = 1 if no way string could be a variable (such as &quot;%value&quot;)<br>C flag = 0 if could be a variable, but no such variable exists at present<br>&nbsp;<br>If not found, and could be a variable, the registers are set up ready for a call to CREATE.<br>&nbsp;<br>BASIC's documentation does not explicitly state, but by prefixing a name with the token for PROC(&amp;F2) or FN (&amp;A4), it may be possible to look up function/procedure names.  <tr> <td valign=top>&amp;40 <td valign=top>CREATE <td>Create a new variable. Input is failure of LVBLNK to find something.<br>&nbsp;<br>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -