flat assembler
Message board for the users of flat assembler.
Index
> Macroinstructions > Macro parameters for constant literals and variable Goto page 1, 2 Next |
Author |
|
shutdownall 05 Aug 2013, 12:24
That's quite easy to understand.
You are using a constant and a label (address) of a (possibly) constant. That's not really the same. Code: prthex 100h ; a const literal prthex myHEX ; a var pquit myHEX dd 100h In the first example your variable "a" is 100h and in the second call your variable "a" is the address of value 100h anywhere in memory. So you can print "a" directly in the first example and have to use indirectly in second example. Code: mov si,a mov ax,si print ax (works for constant) mov si,a mov ax,[si] print ax (works for label) To distinguish both in a macro you can use the example in this thread and handle it differently: http://board.flatassembler.net/topic.php?t=14987 Code: ThisIsConst = 10 ThisIsLabel: if ThisIsConst relativeto $ display "Label" else display "Constant" end if I am not perfect in macros but someone could help you with distinguishing between constants and labels. |
|||
05 Aug 2013, 12:24 |
|
fasmnewbie 05 Aug 2013, 13:19
Thanks for the reply shutdownall.
From what I debugged, my numeric constant "a" is passed to the macro as an address not as a value I am interested in displaying. So what I do is transform it (the constant) into a label inside the macro hoping that it would be addressable as a label from then on. Code: macro prthex a { pusha local ..b ;creates a local label for a jmp @f ..b dd a ;transform it into a local label and... @@: mov si, ..b ; ..collect the address ... } prthex 256d ;prints fine prthex myhex ;prints whatever pquit myhex dd 256d This is the point where this code gets the correct address of "..b" if my "a" was originally a constant. By using this option however, the other "a" real label passed to it will produce incorrect result. Kind of a classic "ying-yang" problem to me I think this could be done by using an IF to distinguish between the two, but since I am not that advanced, for now, I have to use two different macros for displaying each. That "relativeto" example didn't work either. |
|||
05 Aug 2013, 13:19 |
|
fasmnewbie 05 Aug 2013, 13:50
Just to make the problem clearer
Code: macro prthex a { pusha xor si, si if /a is a constant/ ;steps necessary to make it addressable ;put the address into SI ;mov si, b else ;just use the address and put into SI ; mov si, a end if xor ax, ax mov ax, word[si] xor bx, bx mov bx, word[si+2] prtReg bx prtReg ax prtc 'H' popa } I am hoping that somebody can show me that IF part so that I don't have to come up with two different macros for printing a constant and a label parameter. TQVM for your kind replies. |
|||
05 Aug 2013, 13:50 |
|
l_inc 06 Aug 2013, 15:10
fasmnewbie
Your problem is still not clear. Imagine, you're a macro. And I give you an argument 0x800 . Is it a constant or a variable address? The answer is: it can be both. Thus you in fact need either different macros or a way to tell your single macro, how to handle the passed value. Here's an example of a C-like syntax: Code: macro prthex a { define address + define address - match *val,a \{ restore address display \`val\#' is an address',13,10 \} match -,address \{ restore address display \`a\#' is a constant',13,10 \} restore address } prthex 0x800 prthex *0x800 _________________ Faith is a superposition of knowledge and fallacy |
|||
06 Aug 2013, 15:10 |
|
dogman 06 Aug 2013, 19:27
There are a couple ways this is usually done but I have no idea if fasm or any Intel assembler supports this. First you could use keywords and invoke the macro with different keywords depending on whether it's a constant or address. prthex addr=something or prthex constant. The other thing is if the macro language can see the symbol table then it can offer some way of querying the type of operand without a keyword in many cases and you create conditional code based on that. fasm's macro language is intergrated with the assembler, correct? Theoretically it could support this then if it can see the symbol table.
|
|||
06 Aug 2013, 19:27 |
|
BAiC 07 Aug 2013, 11:06
you have dereferencing a pointer/address mixed up with reading its address. when you use the macro you need to dereference the address with brackets like this:
Code: prthex 100h ; a const literal prthex [myHEX] ; a var the macro code will then use eqtype to distinguish between the types. Code: macro testing inp { if (inp eqtype [0]) | (inp eqtype eax) ;code for variable display 'variable' end if if inp eqtype 0 ;code for constant display 'constant' endif } testing [0] testing eax testing 123 _________________ byte me. |
|||
07 Aug 2013, 11:06 |
|
shutdownall 07 Aug 2013, 16:23
BAiC wrote: you have dereferencing a pointer/address mixed up with reading its address. when you use the macro you need to dereference the address with brackets like this: Yes, that's it. You should know it when placing the parameter to the macro. Internally in fasm labels are definetely coded different to constants. But I am not sure if there is (by 'now') a possibility to test a macro parameter on it's type. Eqtype could be a candidate for this and would be probably the best. |
|||
07 Aug 2013, 16:23 |
|
shutdownall 07 Aug 2013, 16:51
By the way - it does work this way.
Here is an example: Code: macro prthex a { virtual @@: dw 0 end virtual if a eqtype @b db 0 else db 1 end if } 0000: [0000] 00 00 lab1 dw 0 0002: [0002] 00 00 00 00 lab2 dd 0 0006: [0006] 01 prthex [lab1] 0007: [0007] 01 prthex [lab2] 0008: [0008] 00 prthex 0 I did put the listing as it shows more detailed what happen. First you define a (anonymous) label in your macro (@@). Then you make a eqtype between the variable a and the anonymous label (referenced with @b). This will put either a databyte 0 if a is any label and databyte 1 if a is any constant. This isn't necessary for your code anymore as a holds the contents of the labels already but this could be helpful maybe for some other issues when distingushing between label and constant. And by the way, why do you always clear register before loading it ? This is not neccessary and has no effect. Code: xor ax,ax mov ax,si |
|||
07 Aug 2013, 16:51 |
|
BAiC 07 Aug 2013, 18:14
shutdownall: you should avoid using @@ in macros since it will interfere with something like the following:
Code: @@: ;continue label. macro_invocation jmp @b this type of bug is very difficult to debug. FASMs eqtype doesn't distinguish between labels and constants so you don't need an anonymous label. you can simply use 0. |
|||
07 Aug 2013, 18:14 |
|
dogman 07 Aug 2013, 18:53
shutdownall wrote: And by the way, why do you always clear register before loading it ? This is not neccessary and has no effect. Oh it definitely has an effect. It makes his code run 90% slower _________________ Sources? Ahahaha! We don't need no stinkin' sources! |
|||
07 Aug 2013, 18:53 |
|
shutdownall 07 Aug 2013, 21:06
BAiC wrote:
I wouldn't say that for all cases. It does distinguish between constants and memory locations referenced by labels. Didn't you check my example ? |
|||
07 Aug 2013, 21:06 |
|
BAiC 07 Aug 2013, 22:54
shutdownall: of course eqtype distinguishes between 0 and [0], that's not the point! eqtype does NOT distinguish between "label:" and "label = $".
|
|||
07 Aug 2013, 22:54 |
|
shutdownall 08 Aug 2013, 19:55
If you refer to previous answers you don't have to repeat my name.
eqtype distinguishes between constants and memory references (address expressions). And that's GREAT. |
|||
08 Aug 2013, 19:55 |
|
fasmnewbie 10 Aug 2013, 12:59
Ok guys thanks for the participation...
I think I have to narrow down the real problem in question... Code: org 100h include 'macro16.inc' macro test a { pusha local ..b, .go xor si, si jmp @f ..b dd a @@: ;push [..b] ;works for label ;push ..b ;works for constant if ~ defined a ;what conditions here? push [..b] ;for label else push ..b ;for constant end if pop si mov ax, word[si] mov bx, word[si+2] prtr bx, -n prtr ax, -n popa } test mydata line test 500d ;1F4h pquit mydata dd 500d ;1F4H See the problem there is getting the correct conditions for that IF so that it can take the correct course. Without the proper conditional setup, I have to alternate between the two commented lines previously for displaying each (a.k.a two different macros) correctly. I have also updated the macro file so that you can test the code yourself. Code: ;Part of macro16.inc ;fl = -n. Do not print the reg's name macro prtr [a,fl] { local .go, .done, ..hextab, .prttext pusha ;..hextab db '0123456789ABCDEF' mov cx, a xor si, si xchg ch, cl if fl eq -n jmp .go end if .prttext: if a eq ax prts "AX:" else if a eq bx prts "BX:" else if a eq cx prts "CX:" else if a eq dx prts "DX:" else if a eq si prts "SI:" else if a eq di prts "DI:" else if a eq sp prts "SP:" else if a eq bp prts "BP:" else if a eq cs prts "CS:" else if a eq ds prts "DS:" else if a eq ss prts "SS:" else if a eq es prts "ES:" end if .go: mov bx, ..hextab ;Get the nibbles mov dl, cl mov dh, ch and cl, 0Fh and dl, 0F0h shr dl, 4 ;Digit Translations mov al, dl xlat [bx] prtc al mov al, cl xlat [bx] prtc al inc si xor bx, bx cmp si, 2 je .done xor bx, bx mov cl, dh ;get the other half jmp .go ..hextab db '0123456789ABCDEF' .done: ;prtc 'H' popa ;..hextab db '0123456789ABCDEF' } macro line { push ax mov ah, 0eh mov al, 0dh int 10h mov al, 0ah int 10h pop ax } macro pquit { mov ah,0h int 16h int 20h ;mov ah, 4ch ;int 21h } Thank you in advance for your kind replies. EDIT: Sorry, I forgot to include the prts and prtc macros ... Here they are; Code: ;Prints both type of string macro prts a { if a eqtype '' prtCStr a else prtStr a end if } ;Prints constant string macro prtCStr [a] { pusha local .go, ..b, .ok xor si,si mov si,..b .go: cmp byte[si],0 je .ok prtc byte[si] inc si jmp .go ..b db a, 0 .ok: popa } ;[var]. Data type db ;0-ended macro prtStr a { push ax mov ah,0eh mov si,a local .loop, .done, .b .loop: cmp byte[si],0 je .done mov al,[si] int 10h add si,1 jmp .loop .done: pop ax } macro prtc a { push ax mov ah, 0eh if ~ a eq al ;prevent perfect mov al, a ;nop for mov al, al end if int 10h pop ax } Last edited by fasmnewbie on 10 Aug 2013, 17:33; edited 3 times in total |
|||
10 Aug 2013, 12:59 |
|
fasmnewbie 10 Aug 2013, 13:07
l_inc wrote: fasmnewbie Hi I_inc That macro works but the answer is persistent for one particular value (label) only. I can't display two different values for the same run. And the macro is way too advance for my "almost-flat" learning curve Thank you for such a nice code. |
|||
10 Aug 2013, 13:07 |
|
fasmnewbie 10 Aug 2013, 13:08
dogman wrote: There are a couple ways this is usually done but I have no idea if fasm or any Intel assembler supports this. First you could use keywords and invoke the macro with different keywords depending on whether it's a constant or address. prthex addr=something or prthex constant. The other thing is if the macro language can see the symbol table then it can offer some way of querying the type of operand without a keyword in many cases and you create conditional code based on that. fasm's macro language is intergrated with the assembler, correct? Theoretically it could support this then if it can see the symbol table. Thank you for your input. |
|||
10 Aug 2013, 13:08 |
|
fasmnewbie 10 Aug 2013, 13:13
shutdownall wrote: By the way - it does work this way. I am still struggling to learn that virtual stuff. But thank you for that effort. I learned a thing or two from that listing. For that xor ax, ax part, well... I am a newbie.. with lots of insecurity in mind. Just wanted to make sure that my entire porn collections don't pop up suddenly in the other half of the register |
|||
10 Aug 2013, 13:13 |
|
fasmnewbie 10 Aug 2013, 13:17
BAiC wrote: you have dereferencing a pointer/address mixed up with reading its address. when you use the macro you need to dereference the address with brackets like this: Thanks for the input. |
|||
10 Aug 2013, 13:17 |
|
l_inc 10 Aug 2013, 17:28
fasmnewbie
Quote: I can't display two different values for the same run. First of all, why not? Look: Code: macro test a { pusha local ..b, .go xor si, si ;push dword [..b] ;works for label ;push dword ..b ;works for constant define address + define address - match *val,a \{ restore address jmp @f ..b dd val @@: push dword [..b] \} match -,address \{ restore address jmp @f ..b dd a @@: push dword ..b \} restore address pop si .go: xor ax, ax mov ax, word[si] xor bx, bx mov bx, word[si+2] prtr bx, -n prtr ax, -n popa } test 500d ;1F4h line test *mydata pquit mydata dd 500d ;1F4H That's what you could do. But your approach is from the beginning is veeery wrong. Firstly, you should start using functions/procedures instead of (or at least together with) macros. Otherwise your code will be bloated with replicated code parts. That's not what macros are intended for. Secondly, your code is full of meaningless and wrong things. Why do you push dword and pop a word (with pop si)? Why do you put the a value into memory at all, if you just need to put it into the ax and bx registers? Why do you sometimes use a single dot prefix and sometimes double dot (your differentiation of those is wrong)? And many more. _________________ Faith is a superposition of knowledge and fallacy |
|||
10 Aug 2013, 17:28 |
|
Goto page 1, 2 Next < Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.