📄 exa6.html
字号:
<code>extern blah function_name(blah, blah)</code> statement.<p>Unlike coding when you are writing a little assembler program, there are solid rules that shouldbe obeyed here:<ul> <li> Registers <code>a1</code> to <code>a4</code> (R0-R3) are alterable. You can corrupt these without worry.<br> <i>All other registers <b>must</b> be preserved.</i> The compiler may have placed values in these registers, such as loop counters, and failure to restore them could have devastating consequences. <li> You <i>should</i> implement an APCS stack frame if your function is likely to call other functions, or is quite large (or if you don't quite trust your code yet - but shhhh, you didn't hear me saying that!).<br> I, personally, find it useful to put in stack frames into most of my development code. Then, if something should go wrong, I can know better where to look. <li> And the one that caught me out, when you use <code>SWI OS_WriteS</code>, always ensure that your strings are null terminated. Otherwise the OS will carry on printing stuff until it reaches a null - some of that stuff having been your instructions!</ul>You will see that we have defined a macro called <code>HEAD</code>. This inserts a functionname just before the APCS stack frame. You can see it in action in the <code>|fix_picture|</code>definition. The macro should be called <i>immediately</i> prior to the code which sets up thestack frame, and it should be before the procedure entry point - as it is not executed. Exactlyas shown. If you enter your function with code before the stack frame is set up (which, initself, is highly unorthodox), you must <tt>B</tt>ranch beyond, as shown:<pre>|my_routine| ...your pre-entry code here... B skip_head_my_routine HEAD ("my_routine")skip_head_my_routine MOV ip, sp STMFD sp!, {a1, a2, fp, ip, lr, pc} SUB fp, ip, #4 ...your routine code... LDMEA fp, {fp, sp, pc}^</pre><font color="red">This is not 32-bit friendly.</font><p>I suppose, at a pinch, such breaking of the rules would be allowed for handlers which need toexit in a real hurry. A sort of <code>CMP a1, #somevalue</code> then <code>MOVNE pc, lr</code>.<p>I should explain, that registers <code>a1</code> and <code>a2</code> contain data passed to thefunction, so they are saved on the stack frame. Also, the value of <code>pc</code> is stored,so it may be evaluated during a backtrace. We don't want to restore it though, so the framepointer value is subtracted by four. <code>ip</code> is used to refer to the original positionof the stack pointer, so write-back doesn't mess it up - this is later restored so the entirestack frame can be easily dumped.For a full explanation of how this stuff works, you will needto consult the PRMs.<p>The code is lightly commented, so no in-line comments will be given. If you are attempting this,it is assumed that you have worked through the earlier examples so can follow my coding...<p><font color = "red">This is not 32-bit friendly.</font><p><pre>; picfixer;; Assembler code for "fixpiccy" utility.;;; Version 0.01 Saturday, 15th July 2000; by Richard Murray;; Downloaded from http://www.heyrick.co.uk/assembler/;a1 RN 0a2 RN 1a3 RN 2a4 RN 3v1 RN 4v2 RN 5v3 RN 6fp RN 11ip RN 12sp RN 13lr RN 14pc RN 15 ; Our code area is <C$$code>, created by the compiler AREA |C$$code|, CODE, READONLY ; Only one procedure to export - the piccy fixer EXPORT |fix_picture| ; This macro sets up the APCS backtrace 'name' MACRO HEAD $name = $name, 0 ALIGN & &FF000000 :OR: (:LEN: $name + 4 :AND: -4) MEND; "fix_picture";; Entry:; R0 = Pointer to full filename; R1 = '1' if quiet mode.;; Uses:; R4 = Preserved copy of filename pointer; R5 = Preserved copy of quiet mode flag; R6 = File handle;; On exit, registers preserved.; HEAD ("fix_picture")|fix_picture| MOV ip, sp STMFD sp!, {a1, a2, fp, ip, lr, pc} SUB fp, ip, #4 STMFD sp!, {v1-v3} MOV v1, a1 ; Preserve filename pointer MOV v2, a2 ; Preserve '-quiet' status MOV v3, #0 ; Open sprite file MOV a2, a1 MOV a1, #&CF ; Open for update (read/write) SWI &2000D ; XOS_Find BVS error_opening CMP a1, #0 ; Valid file handle? BEQ error_opening MOV v3, a1 ; Preserve file handle ; Set file pointer to 52 MOV a1, #1 MOV a2, v3 MOV a3, #52 SWI &20009 ; XOS_Args ; Read byte MOV a2, v3 SWI &2000A ; XOS_BGet BCS read_error CMP a1, #28 ; MODE 28? BEQ is_mode28 CMP a1, #21 ; MODE 21? BEQ is_mode21 ; Else, some other mode... CMP v2, #1 BEQ close_file ; If quiet, return silently SWI &01 ; OS_WriteS = " Sprite is MODE ", 0 ALIGN ADR a2, mode_buffer MOV a3, #4 SWI &DA ; OS_ConvertInteger2 SWI &02 ; OS_Write0 SWI &01 ; OS_WriteS = ", cannot convert this", 13, 10, 13, 10, 0 ALIGNclose_file MOV a1, #0 ; Close file MOV a2, v3 MOV a3, #0 CMP v3, #0 ; Don't do it if file=0 (close all) SWINE &2000D ; XOS_Findreturn LDMFD sp!, {v1-v3} LDMEA fp, {fp, sp, pc}^mode_buffer DCD 0 DCD 0error_opening CMP v2, #1 BEQ return ; If quiet, return silently SWI &01 ; OS_WriteS = " Unable to open file ", 34, 0 ALIGN MOV a1, v1 SWI &02 ; OS_Write0 SWI &01 ; OS_WriteS = 34, 13, 10, 13, 10, 0 ALIGN B returnread_error CMP v2, #1 BEQ close_file ; If quiet, return silently SWI &01 ; OS_WriteS = " Unable to read from file ", 34, 0 ALIGN MOV a1, v1 SWI &02 ; OS_Write0 SWI &01 ; OS_WriteS = 34, 13, 10, 13, 10, 0 ALIGN B close_filewrite_error CMP v2, #1 BEQ close_file ; If quiet, return silently SWI &01 ; OS_WriteS = " Unable to write to file ", 34, 0 ALIGN MOV a1, v1 SWI &02 ; OS_Write0 SWI &01 ; OS_WriteS = 34, 13, 10, 13, 10, 0 ALIGN B close_fileis_mode28 CMP v2, #1 BEQ close_file ; If quiet, return silently SWI &01 ; OS_WriteS = " Sprite is MODE 28, no conversion necessary", 13, 10, 13, 10, 0 ALIGN B close_fileis_mode21 MOV a1, #1 ; Setting file pointer back to 52 MOV a2, v3 MOV a3, #52 SWI &20009 ; XOS_Args MOV a1, #28 MOV a2, v3 SWI &2000B ; XOS_BPut BVS write_error CMP v2, #1 BEQ close_file ; If quiet, return silently SWI &01 ; OS_WriteS = " Sprite converted to MODE 28", 13, 10, 13, 10, 0 ALIGN B close_file END</pre><p><hr size = 3><div align=right><a href="sw/fixpiccy.zip"><i>Download example sources: fixpiccy.zip</i></a><br><font size=-2><i>This code requires <i>objasm</i> and (optionally) Norcroft C</i></font></div><p><hr size = 3><a href="index.html#15">Return to assembler index</a><hr size = 3><address>Copyright © 2000 Richard Murray</address></body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -