flat assembler
Message board for the users of flat assembler.
Index
> Compiler Internals > Understanding internal handling of ORG directive |
Author |
|
Tomasz Grysztar 10 May 2012, 08:58
VIRTUAL directive does restore the original ORG value when the block ends, so you can look at its handler for an example. In principle you need to restore the complete set of variables: org_origin, org_origin_sign, org_registers, org_symbol, org_start in order to restore the ORG value.
|
|||
10 May 2012, 08:58 |
|
shutdownall 10 May 2012, 10:41
Thanks for that hint, will take a look on it this evening.
In the night I had the idea to implement a substract of the code size in the codeblock when restoring but now I try your advice with the org handling in virtual directive. |
|||
10 May 2012, 10:41 |
|
shutdownall 10 May 2012, 10:47
By the way, I found out that during assembling process (assemble.inc) the org value of that label is not availble directly, only the (possible) storage address of the label I think, which is calculated later in formatting process.
That point makes it complicate to realize this function in assembling process but could be worked around with an additional substraction of the codesize after the label. But will check it with virtual directive handling first. |
|||
10 May 2012, 10:47 |
|
Tomasz Grysztar 10 May 2012, 11:34
To define this precisely, some additional terminology is needed. When fasm generates instructions or data it stores them consecutively in a flat memory area, when instruction/directive handler is invoked, EDI register contains the address in that area which is the current "point of assembly", place where the next opcode or data is to be put. With ORG directive programmer specifies for a given "point of assembly" what run-time address should that position correspond to. So we have an assembly-time addresses, the "assembly points", which have to be translated to the run-time addresses. For example the "$" symbol always translates to the run-time address corresponding to the current assembly point.
Now for the internal variables. The "org_start" value is the assembly point of the beginning of current addressing space - this is important for the LOAD/STORE directives, as they are allowed to operate only within this area, which is between the "org_start" and the current assembly point (EDI). The "org_origin" is the value of hypothetical assembly point that would correspond to the run-time address of 0. When some value is specified to ORG directive, the "org_origin" is computed by substracting EDI from that value. The reverse operation can then be used easily compute the run-time address corresponing to any assembly point. For example to compute the "$" value at any time, you need to substract "org_origin" from EDI. In the latest versions of fasm the value of symbol can be larger that 64 bits, therefore there was additional variable "org_origin_sign" holding the higher bits of the "org_origin" value (as the values are currently 65-bit, it is simply sign bit, hence the name). The "org_registers" and "org_symbol" are for the case when the run-time address is relative to registers and/or relocatable section or external symbol. They are therefore also an important part of the address origin storage. |
|||
10 May 2012, 11:34 |
|
shutdownall 10 May 2012, 11:58
Thank you for that excellent and full explanation.
I use the flat model and 16 bit only, so org_origin_sign is not in my 1.69 version (new feature) and not needed and don't use relocation (not now, dont know if ever useful in my 16 bit context). |
|||
10 May 2012, 11:58 |
|
shutdownall 10 May 2012, 22:42
Tomasz Grysztar wrote:
This was very helpful for me. It did not help just to save all variables you named in your other posting. I am not sure, maybe has to do something with EDI. So now I did another way, I computed the actual realtime address like described above and at the end of the codeblock I use a call to org_directive again with that computed value. Works great. Thanks. Here is the code: Code: codeblock_directive: lodsb cmp al,80h jne invalid_operand ; valid instruction only with address value (codeblock at ...) lodsb cmp al,'(' jne invalid_operand ; valid only with immediate or label (no register) cmp byte [org_back],0 jnz missing_end_directive ; check if another "open" codeblock dec esi mov eax,edi sub eax,dword [org_origin] ; compute realtime address (effective address) push edi eax mov edi,org_back ; store org directive with actual effective address for use with "end codeblock" mov al,'(' stosb mov al,2 stosb pop eax stosw mov al,')' stosb mov al,0Fh stosb pop edi jmp org_directive ; do required org for this codeblock end_codeblock: push esi mov esi,org_back call org_directive ; reset org to previous value pop esi xor eax,eax mov byte [org_back],al ; mark codeblock as "closed" ret And here the result in the listing of some sample code: Code: ;labelautodetect ;labelusenumeric format binary AUTOLINE 20 ORG 16514 0000: [4082] 00 14 04 00 EA 33 33 76 VLAB1: REM "NN" VLAB2: 0008: [408A] FF FF FF FF FF FF FF FF db $80 dup($FF) FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF codeblock at VLAB2 0088: [408A] FF db $FF 0089: [408B] C3 8A 40 JP VLAB2 end codeblock 008C: [410A] 99 db $99 codeblock at VLAB1 008D: [4082] 00 00 00 00 00 00 00 00 db $10 dup(0) 00 00 00 00 00 00 00 00 end codeblock 009D: [410B] 63 6F 6E 74 69 6E 75 65 db "continue here again" 20 68 65 72 65 20 61 67 61 69 6E I think now I can easily implement PHASE / DEPHASE instructions to switch org values as described in another post. Some assembler do support this. |
|||
10 May 2012, 22:42 |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.